@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
@@ -1,7 +1,7 @@
1
1
  import { CircleDash } from '@carbon/react/icons';
2
2
  import { zodResolver } from '@hookform/resolvers/zod';
3
- import { parseDate, showSnackbar, useConfig, useSession } from '@openmrs/esm-framework';
4
- import React, { useEffect, useMemo, useState } from 'react';
3
+ import { DefaultWorkspaceProps, parseDate, showSnackbar, useConfig, useSession } from '@openmrs/esm-framework';
4
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
5
5
  import { FieldError, FormProvider, useForm } from 'react-hook-form';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { ConfigObject } from '../../config-schema';
@@ -15,19 +15,20 @@ import {
15
15
  } from '../../core/api/types/stockOperation/StockOperationType';
16
16
  import { TabItem } from '../../core/components/tabs/types';
17
17
  import { otherUser, pick } from '../../core/utils/utils';
18
- import ReceivedItems from '../received-items.component';
19
18
  import {
19
+ BaseStockOperationItemFormData,
20
20
  getStockOperationFormSchema,
21
21
  getStockOperationItemFormSchema,
22
22
  StockOperationItemDtoSchema,
23
23
  } from '../validation-schema';
24
24
  import useOperationTypePermisions from './hooks/useOperationTypePermisions';
25
25
  import BaseOperationDetailsFormStep from './steps/base-operation-details-form-step';
26
+ import ReceivedItems from './steps/received-items.component';
26
27
  import StockOperationItemsFormStep from './steps/stock-operation-items-form-step.component';
27
28
  import StockOperationSubmissionFormStep from './steps/stock-operation-submission-form-step.component';
28
- import StockOperationFormHeader from './stock-operation-form-header.component';
29
- import StockOperationStepper from './stock-operation-stepper/stock-operation-stepper.component';
30
29
  import StockIssueFormInitializerWithRelatedRequisitionOperation from './stock-issue-form-initializer-with-related-requisition-operation.component';
30
+ import StockItemForm, { StockItemFormProps } from './stock-item-form/stock-item-form.workspace';
31
+ import StockOperationStepper from './stock-operation-stepper/stock-operation-stepper.component';
31
32
 
32
33
  /**
33
34
  * Props interface for the StockOperationForm component
@@ -37,7 +38,7 @@ import StockIssueFormInitializerWithRelatedRequisitionOperation from './stock-is
37
38
  * @property {string} [stockRequisitionUuid] - Requisition operation uuid used in stock issue stockOperation type
38
39
  * When undefined or null, the form will be in creation mode.
39
40
  */
40
- type StockOperationFormProps = {
41
+ type StockOperationFormProps = DefaultWorkspaceProps & {
41
42
  stockOperation?: StockOperationDTO;
42
43
  stockOperationType: StockOperationType;
43
44
  stockRequisitionUuid?: string;
@@ -47,6 +48,7 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
47
48
  stockOperation,
48
49
  stockOperationType,
49
50
  stockRequisitionUuid,
51
+ closeWorkspace,
50
52
  }) => {
51
53
  const { t } = useTranslation();
52
54
  const operationType = useMemo(() => {
@@ -59,6 +61,71 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
59
61
  const formschema = useMemo(() => {
60
62
  return getStockOperationFormSchema(operationType);
61
63
  }, [operationType]);
64
+ const showReceivedItems = useMemo(() => {
65
+ return (
66
+ (StockOperationTypeIsStockIssue(stockOperation?.operationType as OperationType) ||
67
+ stockOperation?.permission?.canDisplayReceivedItems) &&
68
+ (stockOperation.status === 'DISPATCHED' || stockOperation.status === 'COMPLETED')
69
+ );
70
+ }, [stockOperation]);
71
+ const {
72
+ user: { uuid: defaultLoggedUserUuid },
73
+ } = useSession();
74
+ const { autoPopulateResponsiblePerson } = useConfig<ConfigObject>();
75
+ const form = useForm<StockOperationItemDtoSchema>({
76
+ defaultValues: {
77
+ responsiblePersonUuid:
78
+ stockOperation?.responsiblePersonUuid ?? // if person uuid exist, make it default
79
+ (stockOperation?.responsiblePersonOther ? otherUser.uuid : undefined) ?? // if other resp person exist, default other user uuid
80
+ (autoPopulateResponsiblePerson ? defaultLoggedUserUuid : undefined), //Else default login user if configured
81
+ operationDate: stockOperation?.operationDate ? parseDate(stockOperation!.operationDate as any) : today(),
82
+ remarks: stockOperation?.remarks ?? '',
83
+
84
+ operationTypeUuid: stockOperation?.operationTypeUuid ?? stockOperationType?.uuid,
85
+ reasonUuid: stockOperation?.reasonUuid ?? '',
86
+ responsiblePersonOther: stockOperation?.responsiblePersonOther ?? '',
87
+ stockOperationItems:
88
+ stockOperation?.stockOperationItems?.map((item) =>
89
+ pick(
90
+ { ...item, expiration: item.expiration ? parseDate(item.expiration as any) : undefined },
91
+ stockOperationItemFormSchema.keyof().options,
92
+ ),
93
+ ) ?? [],
94
+ sourceUuid: stockOperation?.sourceUuid ?? '',
95
+ destinationUuid: stockOperation?.destinationUuid ?? '',
96
+ },
97
+ mode: 'all',
98
+ resolver: zodResolver(formschema),
99
+ });
100
+ const [renderItemForm, setRenderItemForm] = useState(false);
101
+ const [itemsFormProps, setItemFormProps] = useState<StockItemFormProps>();
102
+
103
+ const handleLaunchStockItem = useCallback(
104
+ (stockOperationItem?: BaseStockOperationItemFormData) => {
105
+ setItemFormProps({
106
+ stockOperationType,
107
+ stockOperationItem,
108
+ onSave: (data) => {
109
+ const items = (form.getValues('stockOperationItems') ?? []) as Array<BaseStockOperationItemFormData>;
110
+ const index = items.findIndex((i) => i.uuid === data.uuid);
111
+ if (index === -1) {
112
+ items.push(data);
113
+ } else {
114
+ items[index] = data;
115
+ }
116
+ form.setValue('stockOperationItems', items as any);
117
+ setRenderItemForm(false);
118
+ setItemFormProps(undefined);
119
+ },
120
+ onBack: () => {
121
+ setRenderItemForm(false);
122
+ setItemFormProps(undefined);
123
+ },
124
+ });
125
+ setRenderItemForm(true);
126
+ },
127
+ [stockOperationType, form, setItemFormProps, setRenderItemForm],
128
+ );
62
129
  const steps: TabItem[] = useMemo(() => {
63
130
  return [
64
131
  {
@@ -70,7 +137,7 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
70
137
  onNext={() => setSelectedIndex(1)}
71
138
  />
72
139
  ),
73
- disabled: true,
140
+ disabled: false,
74
141
  },
75
142
  {
76
143
  name: t('stockItems', 'Stock Items'),
@@ -80,9 +147,10 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
80
147
  stockOperationType={stockOperationType}
81
148
  onNext={() => setSelectedIndex(2)}
82
149
  onPrevious={() => setSelectedIndex(0)}
150
+ onLaunchItemsForm={handleLaunchStockItem}
83
151
  />
84
152
  ),
85
- disabled: true,
153
+ disabled: false,
86
154
  },
87
155
  {
88
156
  name: operationTypePermision?.requiresDispatchAcknowledgement ? 'Submit/Dispatch' : 'Submit/Complete',
@@ -91,64 +159,43 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
91
159
  stockOperation={stockOperation}
92
160
  stockOperationType={stockOperationType}
93
161
  onPrevious={() => setSelectedIndex(1)}
162
+ onNext={showReceivedItems ? () => setSelectedIndex(3) : undefined}
163
+ dismissWorkspace={closeWorkspace}
94
164
  />
95
165
  ),
96
- disabled: true,
166
+ disabled: false,
97
167
  },
98
168
  ].concat(
99
- StockOperationTypeIsStockIssue(stockOperation?.operationType as OperationType) ||
100
- stockOperation?.permission?.canDisplayReceivedItems
101
- ? stockOperation.status === 'DISPATCHED' || stockOperation.status === 'COMPLETED'
102
- ? [
103
- {
104
- name: t('receivedItems', 'Received Items'),
105
- component: <ReceivedItems model={stockOperation} />,
106
- disabled: true,
107
- },
108
- ]
109
- : []
169
+ showReceivedItems
170
+ ? [
171
+ {
172
+ name: t('receivedItems', 'Received Items'),
173
+ component: <ReceivedItems stockOperation={stockOperation} onPrevious={() => setSelectedIndex(2)} />,
174
+ disabled: false,
175
+ },
176
+ ]
110
177
  : [],
111
178
  ) as TabItem[];
112
- }, [stockOperation, stockOperationType, t, operationTypePermision]);
113
- const {
114
- user: { uuid: defaultLoggedUserUuid },
115
- } = useSession();
116
- const { autoPopulateResponsiblePerson } = useConfig<ConfigObject>();
117
- const [selectedIndex, setSelectedIndex] = useState(0);
118
- const form = useForm<StockOperationItemDtoSchema>({
119
- // defaultValues: operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE ? issueStockOperation : model,
120
- defaultValues: {
121
- responsiblePersonUuid:
122
- stockOperation?.responsiblePersonUuid ?? // if person uuid exist, make it default
123
- (stockOperation?.responsiblePersonOther ? otherUser.uuid : undefined) ?? // if other resp person exist, default other user uuid
124
- (autoPopulateResponsiblePerson ? defaultLoggedUserUuid : undefined), //Else default login user if configured
125
- operationDate: stockOperation?.operationDate ? parseDate(stockOperation!.operationDate as any) : today(),
126
- remarks: stockOperation?.remarks ?? '',
179
+ }, [
180
+ stockOperation,
181
+ stockOperationType,
182
+ t,
183
+ operationTypePermision,
184
+ showReceivedItems,
185
+ handleLaunchStockItem,
186
+ closeWorkspace,
187
+ ]);
127
188
 
128
- operationTypeUuid: stockOperation?.operationTypeUuid ?? stockOperationType?.uuid,
129
- reasonUuid: stockOperation?.reasonUuid ?? '',
130
- responsiblePersonOther: stockOperation?.responsiblePersonOther ?? '',
131
- stockOperationItems:
132
- stockOperation?.stockOperationItems?.map((item) =>
133
- pick(
134
- { ...item, expiration: item.expiration ? parseDate(item.expiration as any) : undefined },
135
- stockOperationItemFormSchema.keyof().options,
136
- ),
137
- ) ?? [],
138
- sourceUuid: stockOperation?.sourceUuid ?? '',
139
- destinationUuid: stockOperation?.destinationUuid ?? '',
140
- },
141
- mode: 'all',
142
- resolver: zodResolver(formschema),
143
- });
189
+ const [selectedIndex, setSelectedIndex] = useState(0);
144
190
 
145
191
  useEffect(() => {
146
- // Show error snackbar
192
+ // Display fields errors for stock operation items and operation type uuid
147
193
  Object.entries(form.formState.errors ?? {}).forEach(([key, val]) => {
148
194
  if (['stockOperationItems', 'operationTypeUuid'].includes(key)) {
149
- showSnackbar({ kind: 'error', title: key, subtitle: (val[key] as FieldError)?.message });
195
+ showSnackbar({ kind: 'error', title: key, subtitle: (val as FieldError)?.message });
150
196
  }
151
197
  });
198
+
152
199
  // Navigate to step where the error is
153
200
  const fieldSteps = [
154
201
  [
@@ -173,26 +220,26 @@ const StockOperationForm: React.FC<StockOperationFormProps> = ({
173
220
 
174
221
  return (
175
222
  <FormProvider {...form}>
176
- {stockOperation && (
177
- <StockOperationFormHeader stockOperationType={stockOperationType} stockOperation={stockOperation} />
178
- )}
179
223
  {stockOperationType.operationType === OperationType.STOCK_ISSUE_OPERATION_TYPE && (
180
224
  <StockIssueFormInitializerWithRelatedRequisitionOperation
181
225
  stockRequisitionUuid={stockRequisitionUuid as string}
182
226
  stockOperationType={stockOperationType}
183
227
  />
184
228
  )}
185
- <StockOperationStepper
186
- steps={steps.map((tab, index) => ({
187
- title: tab.name,
188
- component: tab.component,
189
- disabled: tab.disabled,
190
- // subTitle: `Subtitle for ${tab.name}`,
191
- icon: <CircleDash />,
192
- }))}
193
- selectedIndex={selectedIndex}
194
- onChange={setSelectedIndex}
195
- />
229
+ {renderItemForm ? (
230
+ <StockItemForm {...itemsFormProps} />
231
+ ) : (
232
+ <StockOperationStepper
233
+ steps={steps.map((tab, index) => ({
234
+ title: tab.name,
235
+ component: tab.component,
236
+ disabled: tab.disabled,
237
+ icon: <CircleDash />,
238
+ }))}
239
+ selectedIndex={selectedIndex}
240
+ onChange={setSelectedIndex}
241
+ />
242
+ )}
196
243
  </FormProvider>
197
244
  );
198
245
  };
@@ -66,15 +66,13 @@
66
66
  }
67
67
 
68
68
  .btnSet {
69
+ width: 100%;
70
+ flex: 1;
69
71
  display: flex;
70
- flex-direction: row;
72
+ flex-direction: row-reverse;
71
73
  gap: layout.$spacing-03;
72
74
  align-items: center;
73
- }
74
-
75
- .relatedLink {
76
- margin-left: layout.$spacing-02;
77
- color: colors.$blue-60;
75
+ margin-top: layout.$spacing-03;
78
76
  }
79
77
 
80
78
  .textHeading {
@@ -90,22 +88,5 @@
90
88
  .statusBody {
91
89
  display: flex;
92
90
  justify-content: space-between;
93
- margin: layout.$spacing-02;
94
- }
95
-
96
- .actionBtns {
97
- margin: layout.$spacing-03;
98
- display: flex;
99
- flex-direction: row;
100
- gap: layout.$spacing-03;
101
- flex-wrap: wrap;
102
- height: fit-content;
103
- }
104
-
105
- .operationlinkscontainer {
106
- margin: layout.$spacing-05;
107
- }
108
-
109
- .relatedTransactionHeader {
110
- color: colors.$green-50;
91
+ align-items: center;
111
92
  }
@@ -1,7 +1,7 @@
1
1
  import React, { useCallback } from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
  import { useStockOperationTypes } from '../../stock-lookups/stock-lookups.resource';
4
- import { launchStockoperationAddOrEditDialog } from '../stock-operation.utils';
4
+ import { launchStockoperationAddOrEditWorkSpace } from '../stock-operation.utils';
5
5
  import { useStockOperationAndItems } from '../stock-operations.resource';
6
6
 
7
7
  interface StockOperationRelatedLinkProps {
@@ -26,7 +26,7 @@ const StockOperationRelatedLink: React.FC<StockOperationRelatedLinkProps> = ({
26
26
  if (!operationType) {
27
27
  return;
28
28
  }
29
- launchStockoperationAddOrEditDialog(
29
+ launchStockoperationAddOrEditWorkSpace(
30
30
  t,
31
31
  operationType,
32
32
  stockOperation,
@@ -4,31 +4,29 @@
4
4
 
5
5
  .layer {
6
6
  display: flex;
7
- flex-direction: column;
7
+ flex-direction: row;
8
8
  gap: layout.$spacing-05;
9
- padding: layout.$spacing-05;
9
+ padding: layout.$spacing-03;
10
+ height: 100%;
10
11
  }
11
12
 
12
13
  .stepperContainer {
13
14
  display: flex;
14
15
  gap: layout.$spacing-03;
15
- flex: 1;
16
- align-items: center;
17
- width: 100%;
16
+ align-items: baseline;
17
+ flex-direction: column;
18
+ width: 200px;
19
+ background-color: colors.$gray-10;
18
20
  }
19
21
 
20
22
  .stepperItem {
21
- flex: 1;
22
- height: 100%;
23
- display: flex;
24
23
  gap: layout.$spacing-03;
25
- align-items: center;
26
24
  padding: layout.$spacing-03;
27
- border-top: layout.$spacing-01 solid colors.$gray-30;
25
+ border-left: layout.$spacing-02 solid colors.$gray-30;
28
26
  }
29
27
 
30
28
  .stepperItemActive {
31
- border-top: layout.$spacing-02 solid var(--brand-03);
29
+ border-left: layout.$spacing-02 solid var(--brand-03);
32
30
  }
33
31
 
34
32
  .subtTitle {
@@ -39,3 +37,8 @@
39
37
  .title {
40
38
  @include type.type-style('heading-02');
41
39
  }
40
+
41
+ .content {
42
+ flex: 1;
43
+ overflow: auto;
44
+ }
@@ -35,16 +35,12 @@ const StockOperationStepper: React.FC<StockOperationStepperProps> = ({
35
35
  key={index}
36
36
  onClick={!disabled ? () => onChange?.(index) : undefined}
37
37
  >
38
- {icon}
39
- <div>
40
- <p className={styles.title}>{title}</p>
41
- <p className={styles.subtTitle}>{subTitle}</p>
42
- </div>
38
+ <p className={styles.title}>{title}</p>
43
39
  </li>
44
40
  );
45
41
  })}
46
42
  </ol>
47
- <Layer>{steps[selectedIndex].component}</Layer>
43
+ <Layer className={styles.content}>{steps[selectedIndex].component}</Layer>
48
44
  </Layer>
49
45
  );
50
46
  };
@@ -37,8 +37,9 @@ import StockOperationTypesSelector from './stock-operation-types-selector/stock-
37
37
  import StockOperationsFilters from './stock-operations-filters.component';
38
38
  import { useStockOperationPages } from './stock-operations-table.resource';
39
39
 
40
+ import { Link } from '@carbon/react';
41
+ import StockOperationExpandedRow from './add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.component';
40
42
  import styles from './stock-operations-table.scss';
41
- import StockOperationStatusRow from './stock-operation-status/stock-operation-status-row';
42
43
 
43
44
  interface StockOperationsTableProps {
44
45
  status?: string;
@@ -49,32 +50,6 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
49
50
  const handleRefresh = () => {
50
51
  handleMutate(`${restBaseUrl}/stockmanagement/stockoperation`);
51
52
  };
52
- const operation: StockOperationType = useMemo(
53
- () => ({
54
- uuid: '',
55
- name: '',
56
- description: '',
57
- operationType: '',
58
- hasSource: false,
59
- sourceType: 'Location',
60
- hasDestination: false,
61
- destinationType: 'Location',
62
- hasRecipient: false,
63
- recipientRequired: false,
64
- availableWhenReserved: false,
65
- allowExpiredBatchNumbers: false,
66
- stockOperationTypeLocationScopes: [],
67
- creator: undefined,
68
- dateCreated: undefined,
69
- changedBy: undefined,
70
- dateChanged: undefined,
71
- dateVoided: undefined,
72
- voidedBy: undefined,
73
- voidReason: '',
74
- voided: false,
75
- }),
76
- [],
77
- );
78
53
 
79
54
  const [selectedFromDate, setSelectedFromDate] = useState(null);
80
55
  const [selectedToDate, setSelectedToDate] = useState(null);
@@ -123,9 +98,13 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
123
98
 
124
99
  const tableRows = useMemo(() => {
125
100
  return items?.map((stockOperation, index) => {
126
- const commonNames = stockOperation?.stockOperationItems
127
- ? stockOperation?.stockOperationItems.map((item) => item.commonName).join(', ')
128
- : '';
101
+ const threshHold = 1;
102
+ const itemCountGreaterThanThreshhold = (stockOperation?.stockOperationItems?.length ?? 0) > threshHold;
103
+ const commonNames =
104
+ stockOperation?.stockOperationItems
105
+ ?.slice(0, itemCountGreaterThanThreshhold ? threshHold : undefined)
106
+ .map((item) => item.commonName)
107
+ .join(', ') ?? '';
129
108
 
130
109
  return {
131
110
  ...stockOperation,
@@ -135,7 +114,10 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
135
114
  operationNumber: (
136
115
  <EditStockOperationActionMenu stockOperation={stockOperation} showIcon={false} showprops={true} />
137
116
  ),
138
- stockOperationItems: commonNames,
117
+ stockOperationItems: {
118
+ commonNames,
119
+ more: itemCountGreaterThanThreshhold ? stockOperation?.stockOperationItems?.length - threshHold : 0,
120
+ },
139
121
  status: `${stockOperation?.status}`,
140
122
  source: `${stockOperation?.sourceName ?? ''}`,
141
123
  destination: `${stockOperation?.destinationName ?? ''}`,
@@ -173,7 +155,16 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
173
155
  headers={tableHeaders}
174
156
  isSortable={true}
175
157
  useZebraStyles={true}
176
- render={({ rows, headers, getHeaderProps, getTableProps, getRowProps, onInputChange }) => (
158
+ render={({
159
+ rows,
160
+ headers,
161
+ getHeaderProps,
162
+ getTableProps,
163
+ getRowProps,
164
+ onInputChange,
165
+ getExpandedRowProps,
166
+ expandRow,
167
+ }) => (
177
168
  <TableContainer>
178
169
  <TableToolbar
179
170
  style={{
@@ -241,19 +232,29 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
241
232
  </TableHead>
242
233
  <TableBody>
243
234
  {rows?.map((row: any, index) => {
235
+ const props = getRowProps({ row });
236
+ const expandedRowProps = getExpandedRowProps({ row });
244
237
  return (
245
238
  <React.Fragment key={row.id}>
246
- <TableExpandRow
247
- className={isDesktop ? styles.desktopRow : styles.tabletRow}
248
- {...getRowProps({ row })}
249
- >
239
+ <TableExpandRow className={isDesktop ? styles.desktopRow : styles.tabletRow} {...props}>
250
240
  {row.cells.map((cell) => (
251
- <TableCell key={cell.id}>{cell.value}</TableCell>
241
+ <TableCell key={cell.id}>
242
+ {cell?.info?.header === 'stockOperationItems' ? (
243
+ <span>
244
+ <span>{cell.value.commonNames}</span>
245
+ {cell.value.more > 0 && (
246
+ <Link onClick={() => expandRow(row.id)}>{`...(${cell.value.more} more)`}</Link>
247
+ )}
248
+ </span>
249
+ ) : (
250
+ cell.value
251
+ )}
252
+ </TableCell>
252
253
  ))}
253
254
  </TableExpandRow>
254
255
  {row.isExpanded ? (
255
256
  <TableExpandedRow colSpan={headers.length + 2}>
256
- <StockOperationStatusRow stockOperation={items[index]} />
257
+ <StockOperationExpandedRow model={items[index]} />
257
258
  </TableExpandedRow>
258
259
  ) : (
259
260
  <TableExpandedRow className={styles.hiddenRow} colSpan={headers.length + 2} />
@@ -1,5 +1,6 @@
1
1
  @use '@carbon/layout';
2
2
  @use '@carbon/type';
3
+ @use '@carbon/colors';
3
4
  @use '~@openmrs/esm-styleguide/src/vars' as *;
4
5
 
5
6
  .tileContainer {
@@ -76,3 +77,22 @@
76
77
  margin-right: 4px;
77
78
  }
78
79
  }
80
+
81
+ .actionBtns {
82
+ display: flex;
83
+ flex-direction: row;
84
+ gap: layout.$spacing-03;
85
+ flex-wrap: wrap;
86
+ height: fit-content;
87
+ justify-content: flex-end;
88
+ flex: 1;
89
+ }
90
+
91
+ .relatedLink {
92
+ margin-left: layout.$spacing-02;
93
+ color: colors.$blue-60;
94
+ }
95
+
96
+ .relatedTransactionHeader {
97
+ color: colors.$green-50;
98
+ }