@openmrs/esm-stock-management-app 3.0.1-pre.840 → 3.0.1-pre.848
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.
- package/dist/10.js +1 -1
- package/dist/119.js +1 -1
- package/dist/14.js +1 -0
- package/dist/14.js.map +1 -0
- package/dist/152.js +1 -0
- package/dist/152.js.map +1 -0
- package/dist/172.js +1 -1
- package/dist/172.js.map +1 -1
- package/dist/20.js +1 -1
- package/dist/235.js +1 -0
- package/dist/235.js.map +1 -0
- package/dist/290.js +1 -1
- package/dist/290.js.map +1 -1
- package/dist/467.js +1 -1
- package/dist/574.js +1 -1
- package/dist/606.js +1 -1
- package/dist/627.js +1 -1
- package/dist/642.js +1 -1
- package/dist/675.js +1 -1
- package/dist/703.js +1 -0
- package/dist/703.js.map +1 -0
- package/dist/727.js +1 -1
- package/dist/842.js +2 -0
- package/dist/842.js.map +1 -0
- package/dist/93.js +1 -1
- package/dist/93.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-stock-management-app.js +1 -1
- package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +133 -61
- package/dist/openmrs-esm-stock-management-app.js.map +1 -1
- package/dist/routes.json +1 -1
- package/package.json +1 -1
- package/src/core/components/card/metrics-card-component.tsx +24 -21
- package/src/core/components/card/metrics-card.scss +46 -8
- package/src/core/components/overlay/overlay.scss +1 -1
- package/src/core/components/privilages-component/privilages.scss +1 -1
- package/src/core/components/table/table.scss +1 -1
- package/src/core/components/tabs/vertical-tabs.scss +1 -1
- package/src/dashboard/home-dashboard.scss +0 -4
- package/src/index.ts +61 -42
- package/src/routes.json +12 -4
- package/src/stock-home/{stock-home-inventory-expiry.component.tsx → expired-stock.modal.tsx} +26 -14
- package/src/stock-home/{stock-home-issuing-modal.component.tsx → issuing-stock.modal.tsx} +26 -14
- package/src/stock-home/{stock-home-receiving-modal.component.tsx → receiving-stock.modal.tsx} +27 -20
- package/src/stock-home/stock-home-detail-card.scss +24 -30
- package/src/stock-home/stock-home-detail-cards.component.tsx +34 -33
- package/src/stock-home/stock-home-inventory-card.component.tsx +19 -33
- package/src/stock-home/{stock-home-inventory-expiry.resource.tsx → stock-home-inventory-expiry.resource.ts} +2 -7
- package/src/stock-home/{stock-home-inventory-items.resource.tsx → stock-home-inventory-items.resource.ts} +2 -1
- package/src/stock-home/stock-home-issuing-card.component.tsx +17 -28
- package/src/stock-home/stock-home-landing-page-component.tsx +1 -3
- package/src/stock-home/{stock-home-metrics.tsx → stock-home-metrics.component.tsx} +37 -40
- package/src/stock-home/stock-home-receiving-card.component.tsx +16 -27
- package/src/stock-home/stock-home.scss +5 -5
- package/src/stock-items/add-stock-item/stock-item-details/stock-item-details.scss +1 -1
- package/src/stock-items/add-stock-item/stock-item-rules/add-stock-rule-button.component.tsx +1 -1
- package/src/stock-items/stock-items-table.scss +6 -9
- package/src/stock-items/stock-items.component.tsx +1 -1
- package/src/stock-locations/stock-locations.component.tsx +1 -1
- package/src/stock-management-header/stock-management-header.scss +1 -1
- package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.scss +1 -1
- package/src/stock-operations/stock-operations-filters.component.tsx +5 -5
- package/src/stock-operations/stock-operations-table.component.tsx +66 -73
- package/src/stock-operations/stock-operations-table.scss +18 -9
- package/src/stock-operations/stock-operations.component.tsx +1 -1
- package/src/stock-reports/report-list/stock-reports.scss +1 -1
- package/src/stock-sources/add-stock-sources/add-stock-sources.scss +1 -1
- package/src/stock-sources/delete-stock-modal.scss +1 -1
- package/src/stock-sources/stock-sources.component.tsx +1 -1
- package/src/stock-user-role-scopes/delete-stock-user-scope-modal.scss +1 -1
- package/src/stock-user-role-scopes/stock-user-role-scopes.component.tsx +1 -1
- package/src/stock-user-role-scopes/stock-user-role-scopes.scss +1 -1
- package/translations/en.json +34 -29
- package/dist/165.js +0 -2
- package/dist/165.js.map +0 -1
- package/dist/769.js +0 -1
- package/dist/769.js.map +0 -1
- /package/dist/{165.js.LICENSE.txt → 842.js.LICENSE.txt} +0 -0
- /package/src/stock-home/{stock-home-issuing.resource.tsx → stock-home-issuing.resource.ts} +0 -0
- /package/src/stock-home/{stock-home-receiving.resource.tsx → stock-home-receiving.resource.ts} +0 -0
@@ -1,9 +1,10 @@
|
|
1
|
+
@use '@carbon/colors';
|
1
2
|
@use '@carbon/layout';
|
2
3
|
@use '@carbon/type';
|
3
|
-
@use '
|
4
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
4
5
|
|
5
6
|
.container {
|
6
|
-
margin:
|
7
|
+
margin: layout.$spacing-07 0;
|
7
8
|
}
|
8
9
|
|
9
10
|
.emptyStateContainer,
|
@@ -12,13 +13,9 @@
|
|
12
13
|
}
|
13
14
|
|
14
15
|
.tilesContainer {
|
15
|
-
background-color: $ui-02;
|
16
16
|
border: 1px solid $ui-03;
|
17
|
-
|
17
|
+
min-height: 7.875rem;
|
18
18
|
width: 100%;
|
19
|
-
margin: 0 auto;
|
20
|
-
max-width: 95vw;
|
21
|
-
padding-bottom: 0;
|
22
19
|
}
|
23
20
|
|
24
21
|
.headerContainer {
|
@@ -92,13 +89,13 @@
|
|
92
89
|
@include type.type-style('heading-compact-01');
|
93
90
|
color: $text-02;
|
94
91
|
margin-top: layout.$spacing-05;
|
95
|
-
margin-bottom: layout.$spacing-03;
|
96
92
|
}
|
97
93
|
|
98
94
|
.desktopHeading,
|
99
95
|
.tabletHeading {
|
100
96
|
text-align: left;
|
101
97
|
text-transform: capitalize;
|
98
|
+
margin-bottom: layout.$spacing-05;
|
102
99
|
|
103
100
|
h4 {
|
104
101
|
@include type.type-style('heading-compact-02');
|
@@ -115,11 +112,6 @@
|
|
115
112
|
}
|
116
113
|
}
|
117
114
|
|
118
|
-
.tile {
|
119
|
-
text-align: center;
|
120
|
-
border: 1px solid $ui-03;
|
121
|
-
}
|
122
|
-
|
123
115
|
.filterEmptyState {
|
124
116
|
display: flex;
|
125
117
|
justify-content: center;
|
@@ -146,24 +138,26 @@
|
|
146
138
|
|
147
139
|
.cardContainer {
|
148
140
|
display: flex;
|
149
|
-
|
141
|
+
padding: layout.$spacing-05;
|
142
|
+
background-color: #ffffff;
|
143
|
+
flex-flow: row wrap;
|
144
|
+
flex-grow: 1;
|
145
|
+
gap: layout.$spacing-05;
|
146
|
+
align-items: stretch;
|
150
147
|
}
|
151
148
|
|
152
149
|
.cardContainer > * {
|
153
|
-
flex: 1;
|
154
|
-
|
155
|
-
}
|
156
|
-
|
157
|
-
.cardContainerBig {
|
158
|
-
display: flex;
|
159
|
-
flex-direction: column;
|
150
|
+
flex: 1 1 0;
|
151
|
+
height: 100%;
|
160
152
|
}
|
161
153
|
|
162
154
|
.card {
|
163
155
|
display: flex;
|
164
|
-
|
156
|
+
flex-direction: column;
|
165
157
|
margin: 10px;
|
166
|
-
background-color:
|
158
|
+
background-color: colors.$gray-10;
|
159
|
+
height: 100%;
|
160
|
+
justify-content: space-between;
|
167
161
|
}
|
168
162
|
|
169
163
|
.icon {
|
@@ -172,31 +166,31 @@
|
|
172
166
|
|
173
167
|
.colorLineYellow {
|
174
168
|
width: 5px;
|
175
|
-
background-color:
|
169
|
+
background-color: colors.$yellow-30;
|
176
170
|
margin-right: 10px;
|
177
171
|
}
|
178
172
|
|
179
173
|
.colorLineBlue {
|
180
174
|
width: 5px;
|
181
|
-
background-color:
|
175
|
+
background-color: colors.$blue-60;
|
182
176
|
margin-right: 10px;
|
183
177
|
}
|
184
178
|
|
185
179
|
.colorLineOrange {
|
186
180
|
width: 5px;
|
187
|
-
background-color:
|
181
|
+
background-color: colors.$orange-40;
|
188
182
|
margin-right: 10px;
|
189
183
|
}
|
190
184
|
|
191
185
|
.colorLineGreen {
|
192
186
|
width: 5px;
|
193
|
-
background-color:
|
187
|
+
background-color: colors.$green-60;
|
194
188
|
margin-right: 10px;
|
195
189
|
}
|
196
190
|
|
197
191
|
.colorLineRed {
|
198
192
|
width: 5px;
|
199
|
-
background-color:
|
193
|
+
background-color: colors.$red-60;
|
200
194
|
margin-right: 10px;
|
201
195
|
}
|
202
196
|
|
@@ -206,6 +200,6 @@
|
|
206
200
|
}
|
207
201
|
|
208
202
|
.cardText p {
|
209
|
-
font-size:
|
210
|
-
color:
|
203
|
+
font-size: layout.$spacing-05;
|
204
|
+
color: colors.$gray-70;
|
211
205
|
}
|
@@ -1,48 +1,49 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useTranslation } from 'react-i18next';
|
3
|
+
import { Layer, Tile } from '@carbon/react';
|
3
4
|
import { useLayoutType } from '@openmrs/esm-framework';
|
4
5
|
import StockHomeInventoryCard from './stock-home-inventory-card.component';
|
5
|
-
import StockHomeReceivingCard from './stock-home-receiving-card.component';
|
6
6
|
import StockHomeIssuingCard from './stock-home-issuing-card.component';
|
7
|
-
import
|
7
|
+
import StockHomeReceivingCard from './stock-home-receiving-card.component';
|
8
8
|
import styles from './stock-home-detail-card.scss';
|
9
9
|
|
10
|
-
|
10
|
+
interface DetailCardProps {
|
11
|
+
title: string;
|
12
|
+
children: React.ReactNode;
|
13
|
+
}
|
14
|
+
|
15
|
+
const DetailCard: React.FC<DetailCardProps> = ({ title, children }) => {
|
11
16
|
const isTablet = useLayoutType() === 'tablet';
|
17
|
+
const responsiveStyles = isTablet ? styles.tabletHeading : styles.desktopHeading;
|
18
|
+
|
19
|
+
return (
|
20
|
+
<div className={styles.tilesContainer}>
|
21
|
+
<Layer>
|
22
|
+
<Tile>
|
23
|
+
<div className={responsiveStyles}>
|
24
|
+
<h4>{title}</h4>
|
25
|
+
</div>
|
26
|
+
{children}
|
27
|
+
</Tile>
|
28
|
+
</Layer>
|
29
|
+
</div>
|
30
|
+
);
|
31
|
+
};
|
32
|
+
|
33
|
+
const StockHomeDetailCards: React.FC = () => {
|
12
34
|
const { t } = useTranslation();
|
13
35
|
|
14
36
|
return (
|
15
37
|
<div className={styles.cardContainer}>
|
16
|
-
<
|
17
|
-
<
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
</div>
|
26
|
-
<div className={styles.tilesContainer}>
|
27
|
-
<Layer>
|
28
|
-
<Tile>
|
29
|
-
<div className={isTablet ? styles.tabletHeading : styles.desktopHeading}>
|
30
|
-
<h4>{t('receiving', 'Receiving')}</h4>
|
31
|
-
</div>
|
32
|
-
<StockHomeReceivingCard />
|
33
|
-
</Tile>
|
34
|
-
</Layer>
|
35
|
-
</div>
|
36
|
-
<div className={styles.tilesContainer}>
|
37
|
-
<Layer>
|
38
|
-
<Tile>
|
39
|
-
<div className={isTablet ? styles.tabletHeading : styles.desktopHeading}>
|
40
|
-
<h4>{t('issuing', 'Issuing')}</h4>
|
41
|
-
</div>
|
42
|
-
<StockHomeIssuingCard />
|
43
|
-
</Tile>
|
44
|
-
</Layer>
|
45
|
-
</div>
|
38
|
+
<DetailCard title={t('inventoryAlerts', 'Inventory alerts')}>
|
39
|
+
<StockHomeInventoryCard />
|
40
|
+
</DetailCard>
|
41
|
+
<DetailCard title={t('receiving', 'Receiving')}>
|
42
|
+
<StockHomeReceivingCard />
|
43
|
+
</DetailCard>
|
44
|
+
<DetailCard title={t('issuing', 'Issuing')}>
|
45
|
+
<StockHomeIssuingCard />
|
46
|
+
</DetailCard>
|
46
47
|
</div>
|
47
48
|
);
|
48
49
|
};
|
@@ -1,30 +1,23 @@
|
|
1
|
-
import React
|
1
|
+
import React from 'react';
|
2
2
|
import { useTranslation } from 'react-i18next';
|
3
3
|
import { Button } from '@carbon/react';
|
4
|
-
import { navigate, useLayoutType } from '@openmrs/esm-framework';
|
5
|
-
import styles from './stock-home-detail-card.scss';
|
6
4
|
import { WarningHex } from '@carbon/react/icons';
|
5
|
+
import { showModal } from '@openmrs/esm-framework';
|
7
6
|
import { useStockInventory } from './stock-home-inventory-expiry.resource';
|
8
7
|
import { useStockInventoryItems } from './stock-home-inventory-items.resource';
|
9
|
-
import
|
8
|
+
import styles from './stock-home-detail-card.scss';
|
10
9
|
|
11
10
|
const StockHomeInventoryCard = () => {
|
12
11
|
const { t } = useTranslation();
|
13
|
-
const isTablet = useLayoutType() === 'tablet';
|
14
|
-
|
15
12
|
const { items: expiryItems, isLoading: inventoryLoading } = useStockInventory();
|
16
13
|
const { items: stockItems, isLoading } = useStockInventoryItems();
|
17
14
|
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
if (isLoading || inventoryLoading) {
|
16
|
+
return null;
|
17
|
+
}
|
21
18
|
|
22
19
|
if (stockItems?.length === 0) {
|
23
|
-
return (
|
24
|
-
<>
|
25
|
-
<p className={styles.content}>{t('inventoryAlertNull', 'No inventory alerts to display')}</p>
|
26
|
-
</>
|
27
|
-
);
|
20
|
+
return <p>{t('noInventoryAlerts', 'No inventory alerts to display')}</p>;
|
28
21
|
}
|
29
22
|
|
30
23
|
const currentDate = new Date();
|
@@ -44,6 +37,13 @@ const StockHomeInventoryCard = () => {
|
|
44
37
|
})
|
45
38
|
.slice(0, 5);
|
46
39
|
|
40
|
+
const launchExpiredStockModal = () => {
|
41
|
+
const dispose = showModal('expired-stock-modal', {
|
42
|
+
closeModal: () => dispose(),
|
43
|
+
expiredStock: mergedArray,
|
44
|
+
});
|
45
|
+
};
|
46
|
+
|
47
47
|
return (
|
48
48
|
<>
|
49
49
|
{filteredData.map((item, index) => (
|
@@ -53,31 +53,17 @@ const StockHomeInventoryCard = () => {
|
|
53
53
|
<WarningHex size={40} color={'#DA1E28'} />
|
54
54
|
</div>
|
55
55
|
<div className={styles.cardText}>
|
56
|
-
<p>
|
56
|
+
<p>{t('expiringStock', 'Expiring stock')}</p>
|
57
57
|
<p>
|
58
|
-
<strong>{item?.drugName}</strong> Batch No: {item?.batchNo} Quantity:
|
59
|
-
{item?.dispensingUnitName}
|
58
|
+
<strong>{item?.drugName}</strong> {t('batchNo', 'Batch No:')} {item?.batchNo} {t('quantity', 'Quantity:')}{' '}
|
59
|
+
{item?.quantity} {item?.dispensingUnitName}
|
60
60
|
</p>
|
61
61
|
</div>
|
62
62
|
</div>
|
63
63
|
))}
|
64
|
-
{
|
65
|
-
|
66
|
-
navigate({
|
67
|
-
to: `${window.getOpenmrsSpaBase()}stock-management/expired-stock`,
|
68
|
-
});
|
69
|
-
}}
|
70
|
-
kind="ghost"
|
71
|
-
>
|
72
|
-
View All
|
73
|
-
</Button> */}
|
74
|
-
|
75
|
-
<Button onClick={() => setModalOpen(true)} kind="ghost">
|
76
|
-
View All
|
64
|
+
<Button kind="ghost" onClick={launchExpiredStockModal} size="sm">
|
65
|
+
{t('viewAll', 'View All')}
|
77
66
|
</Button>
|
78
|
-
|
79
|
-
{/* Expired Stock Modal */}
|
80
|
-
<ExpiredStockModal open={isModalOpen} onClose={() => setModalOpen(false)} expiredStock={mergedArray} />
|
81
67
|
</>
|
82
68
|
);
|
83
69
|
};
|
@@ -1,11 +1,6 @@
|
|
1
1
|
import { ResourceRepresentation } from '../core/api/api';
|
2
|
-
import { useEffect,
|
3
|
-
import {
|
4
|
-
type StockBatchFilter,
|
5
|
-
StockItemInventoryFilter,
|
6
|
-
useStockBatches,
|
7
|
-
useStockItemInventory,
|
8
|
-
} from '../stock-items/stock-items.resource';
|
2
|
+
import { useEffect, useState } from 'react';
|
3
|
+
import { type StockBatchFilter, useStockBatches } from '../stock-items/stock-items.resource';
|
9
4
|
|
10
5
|
export function useStockInventory() {
|
11
6
|
const [stockItemFilter, setStockItemFilter] = useState<StockBatchFilter>({
|
@@ -1,6 +1,7 @@
|
|
1
|
-
import { type StockItemFilter, useStockItems } from '../stock-items/stock-items.resource';
|
2
1
|
import { useEffect, useState } from 'react';
|
2
|
+
import { type StockItemFilter, useStockItems } from '../stock-items/stock-items.resource';
|
3
3
|
import { ResourceRepresentation } from '../core/api/api';
|
4
|
+
|
4
5
|
export function useStockInventoryItems(v?: ResourceRepresentation) {
|
5
6
|
const [stockItemFilter, setStockItemFilter] = useState<StockItemFilter>({
|
6
7
|
v: v || ResourceRepresentation.Default,
|
@@ -1,32 +1,26 @@
|
|
1
|
-
import React
|
1
|
+
import React from 'react';
|
2
2
|
import { useTranslation } from 'react-i18next';
|
3
3
|
import { Button } from '@carbon/react';
|
4
|
-
import { navigate, useLayoutType } from '@openmrs/esm-framework';
|
5
|
-
import styles from './stock-home-detail-card.scss';
|
6
4
|
import { ResourceRepresentation } from '../core/api/api';
|
7
|
-
import { DocumentImport } from '@carbon/react/icons';
|
5
|
+
import { DocumentImport, View } from '@carbon/react/icons';
|
6
|
+
import { showModal } from '@openmrs/esm-framework';
|
8
7
|
import { useStockIssuing } from './stock-home-issuing.resource';
|
9
|
-
import
|
8
|
+
import styles from './stock-home-detail-card.scss';
|
10
9
|
|
11
10
|
const StockHomeIssuingCard = () => {
|
12
11
|
const { t } = useTranslation();
|
13
|
-
const isTablet = useLayoutType() === 'tablet';
|
14
12
|
|
15
13
|
const { items, isLoading } = useStockIssuing({
|
16
14
|
v: ResourceRepresentation.Full,
|
17
15
|
totalCount: true,
|
18
16
|
});
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
if (isLoading) {
|
19
|
+
return null;
|
20
|
+
}
|
23
21
|
|
24
22
|
if (items?.length === 0) {
|
25
|
-
return (
|
26
|
-
<>
|
27
|
-
<p className={styles.content}>{t('issuingNull', 'No issued to display')}</p>
|
28
|
-
</>
|
29
|
-
);
|
23
|
+
return <p className={styles.content}>{t('noIssuedStock', 'No issued stock to display')}</p>;
|
30
24
|
}
|
31
25
|
|
32
26
|
const itemsToDisplay = items?.map((item, index) => {
|
@@ -49,6 +43,13 @@ const StockHomeIssuingCard = () => {
|
|
49
43
|
|
50
44
|
const flattenedItemsToDisplay = itemsToDisplay?.flat().slice(0, 10);
|
51
45
|
|
46
|
+
const launchIssuingStockModal = () => {
|
47
|
+
const dispose = showModal('issuing-stock-modal', {
|
48
|
+
closeModal: () => dispose(),
|
49
|
+
issuingStock: items,
|
50
|
+
});
|
51
|
+
};
|
52
|
+
|
52
53
|
return (
|
53
54
|
<>
|
54
55
|
{flattenedItemsToDisplay?.map((item, index) => (
|
@@ -67,21 +68,9 @@ const StockHomeIssuingCard = () => {
|
|
67
68
|
</div>
|
68
69
|
</div>
|
69
70
|
))}
|
70
|
-
{
|
71
|
-
|
72
|
-
navigate({
|
73
|
-
to: `${window.getOpenmrsSpaBase()}stock-management/requisitions`,
|
74
|
-
});
|
75
|
-
}}
|
76
|
-
kind="ghost"
|
77
|
-
>
|
78
|
-
View All
|
79
|
-
</Button> */}
|
80
|
-
<Button onClick={() => setModalOpen(true)} kind="ghost">
|
81
|
-
View All
|
71
|
+
<Button kind="ghost" onClick={launchIssuingStockModal} size="sm">
|
72
|
+
{t('viewAll', 'View All')}
|
82
73
|
</Button>
|
83
|
-
|
84
|
-
<IssuingStockModal open={isModalOpen} onClose={() => setModalOpen(false)} issuingStock={items} />
|
85
74
|
</>
|
86
75
|
);
|
87
76
|
};
|
@@ -1,10 +1,8 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { StockManagementHeader } from '../stock-management-header/stock-management-header.component';
|
3
|
-
import StockManagementMetrics from './stock-home-metrics';
|
4
2
|
import StockHomeDetailCards from './stock-home-detail-cards.component';
|
3
|
+
import StockManagementMetrics from './stock-home-metrics.component';
|
5
4
|
|
6
5
|
export default function StockHomeLandingPage() {
|
7
|
-
const basePath = `${window.getOpenmrsSpaBase()}stock-management`;
|
8
6
|
return (
|
9
7
|
<div style={{ backgroundColor: 'white' }}>
|
10
8
|
<StockManagementMetrics />
|
@@ -2,19 +2,17 @@ import React from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
3
3
|
import { InlineLoading } from '@carbon/react';
|
4
4
|
import { ErrorState } from '@openmrs/esm-framework';
|
5
|
-
import styles from './stock-home.scss';
|
6
|
-
import MetricsCard from '../core/components/card/metrics-card-component';
|
7
|
-
import useStockList from './useStockList';
|
8
|
-
|
9
|
-
import { type StockOperationFilter } from '../stock-operations/stock-operations.resource';
|
10
5
|
import { useDisposalList } from './useDisposalList';
|
11
6
|
import { ResourceRepresentation } from '../core/api/api';
|
12
7
|
import { useStockInventoryItems } from './stock-home-inventory-items.resource';
|
13
8
|
import { useStockInventory } from './stock-home-inventory-expiry.resource';
|
9
|
+
import { type StockOperationFilter } from '../stock-operations/stock-operations.resource';
|
10
|
+
import useStockList from './useStockList';
|
11
|
+
import MetricsCard from '../core/components/card/metrics-card-component';
|
12
|
+
import styles from './stock-home.scss';
|
14
13
|
|
15
14
|
const StockManagementMetrics: React.FC = (filter: StockOperationFilter) => {
|
16
15
|
const { t } = useTranslation();
|
17
|
-
|
18
16
|
const { stockList: allStocks, isLoading, error } = useStockList();
|
19
17
|
const { items: expiryItems, isLoading: inventoryLoading } = useStockInventory();
|
20
18
|
const { items: stockItems } = useStockInventoryItems();
|
@@ -45,48 +43,47 @@ const StockManagementMetrics: React.FC = (filter: StockOperationFilter) => {
|
|
45
43
|
if (isLoading) {
|
46
44
|
return <InlineLoading role="progressbar" description={t('loading', 'Loading...')} />;
|
47
45
|
}
|
46
|
+
|
48
47
|
if (error) {
|
49
48
|
return <ErrorState headerTitle={t('errorStockMetric', 'Error fetching stock metrics')} error={error} />;
|
50
49
|
}
|
51
50
|
|
52
51
|
const filteredItems =
|
53
52
|
items && items.filter((item) => item.reasonName === 'Drug not available due to expired medication');
|
54
|
-
const
|
53
|
+
const poorQualityItems = items && items.filter((item) => item.reasonName === 'Poor Quality');
|
55
54
|
|
56
55
|
return (
|
57
|
-
|
58
|
-
<
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
</div>
|
89
|
-
</>
|
56
|
+
<div className={styles.cardContainer}>
|
57
|
+
<MetricsCard
|
58
|
+
count={{
|
59
|
+
expiry6months: sixMonthsExpiryStocks,
|
60
|
+
}}
|
61
|
+
headerLabel={t('expiringStock', 'Expiring stock')}
|
62
|
+
label={t('expiringStock', 'Expiring stock')}
|
63
|
+
value={filteredData?.length || 0}
|
64
|
+
view="items"
|
65
|
+
/>
|
66
|
+
<MetricsCard
|
67
|
+
label={t('outOfStock', 'Out of stock')}
|
68
|
+
headerLabel={t('outOfStock', 'Out of stock')}
|
69
|
+
outOfStockCount={{
|
70
|
+
itemsBelowMin: [],
|
71
|
+
itemsAboveMax: [],
|
72
|
+
}}
|
73
|
+
value={allStocks?.length}
|
74
|
+
view="items"
|
75
|
+
/>
|
76
|
+
<MetricsCard
|
77
|
+
disposedCount={{
|
78
|
+
expired: filteredItems,
|
79
|
+
poorQuality: poorQualityItems,
|
80
|
+
}}
|
81
|
+
headerLabel={t('disposedStock', 'Disposed stock')}
|
82
|
+
label={t('disposedStock', 'Disposed stock')}
|
83
|
+
value={items?.length || 0}
|
84
|
+
view="items"
|
85
|
+
/>
|
86
|
+
</div>
|
90
87
|
);
|
91
88
|
};
|
92
89
|
export default StockManagementMetrics;
|
@@ -1,34 +1,35 @@
|
|
1
|
-
import React
|
1
|
+
import React from 'react';
|
2
2
|
import { useTranslation } from 'react-i18next';
|
3
3
|
import { Button } from '@carbon/react';
|
4
|
-
import { navigate, useLayoutType } from '@openmrs/esm-framework';
|
5
|
-
import styles from './stock-home-detail-card.scss';
|
6
4
|
import { Delivery } from '@carbon/react/icons';
|
5
|
+
import { showModal } from '@openmrs/esm-framework';
|
7
6
|
import { ResourceRepresentation } from '../core/api/api';
|
8
7
|
import { useStockReceiving } from './stock-home-receiving.resource';
|
9
|
-
import
|
8
|
+
import styles from './stock-home-detail-card.scss';
|
10
9
|
|
11
10
|
const StockHomeReceivingCard = () => {
|
12
11
|
const { t } = useTranslation();
|
13
|
-
const isTablet = useLayoutType() === 'tablet';
|
14
12
|
|
15
13
|
const { items, isLoading } = useStockReceiving({
|
16
14
|
v: ResourceRepresentation.Full,
|
17
15
|
totalCount: true,
|
18
16
|
});
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
if (isLoading) {
|
19
|
+
return null;
|
20
|
+
}
|
23
21
|
|
24
22
|
if (items?.length === 0) {
|
25
|
-
return (
|
26
|
-
<>
|
27
|
-
<p className={styles.content}>{t('receivedNull', 'No received to display')}</p>
|
28
|
-
</>
|
29
|
-
);
|
23
|
+
return <p className={styles.content}>{t('noReceivedStock', 'No received stock to display')}</p>;
|
30
24
|
}
|
31
25
|
|
26
|
+
const launchReceivingStockModal = () => {
|
27
|
+
const dispose = showModal('receiving-stock-modal', {
|
28
|
+
closeModal: () => dispose(),
|
29
|
+
receivingStock: items,
|
30
|
+
});
|
31
|
+
};
|
32
|
+
|
32
33
|
return (
|
33
34
|
<>
|
34
35
|
{items?.map((item, index) =>
|
@@ -49,21 +50,9 @@ const StockHomeReceivingCard = () => {
|
|
49
50
|
</div>
|
50
51
|
)),
|
51
52
|
)}
|
52
|
-
{
|
53
|
-
|
54
|
-
navigate({
|
55
|
-
to: `${window.getOpenmrsSpaBase()}stock-management/orders`,
|
56
|
-
});
|
57
|
-
}}
|
58
|
-
kind="ghost"
|
59
|
-
>
|
60
|
-
{t('receivedView', 'View All')}
|
61
|
-
</Button> */}
|
62
|
-
<Button onClick={() => setModalOpen(true)} kind="ghost">
|
63
|
-
{t('receivedView', 'View All')}
|
53
|
+
<Button kind="ghost" onClick={launchReceivingStockModal} size="sm">
|
54
|
+
{t('viewAll', 'View All')}
|
64
55
|
</Button>
|
65
|
-
|
66
|
-
<ReceivingStockModal open={isModalOpen} onClose={() => setModalOpen(false)} receivingStock={items} />
|
67
56
|
</>
|
68
57
|
);
|
69
58
|
};
|
@@ -1,13 +1,13 @@
|
|
1
1
|
@use '@carbon/layout';
|
2
2
|
@use '@carbon/type';
|
3
3
|
@use '@carbon/colors';
|
4
|
-
@use '
|
4
|
+
@use '@openmrs/esm-styleguide/src/vars' as *;
|
5
|
+
|
5
6
|
.cardContainer {
|
6
7
|
background-color: colors.$white;
|
7
8
|
display: flex;
|
8
|
-
justify-content: space-between;
|
9
|
-
margin: 0 layout.$spacing-05 0 layout.$spacing-05;
|
10
9
|
flex-flow: row wrap;
|
11
|
-
|
12
|
-
|
10
|
+
gap: layout.$spacing-05;
|
11
|
+
justify-content: space-between;
|
12
|
+
padding: layout.$spacing-05;
|
13
13
|
}
|
@@ -12,7 +12,7 @@ const AddStockRuleActionButton: React.FC<AddStockRuleActionButtonProps> = ({ sto
|
|
12
12
|
|
13
13
|
const handleClick = useCallback(() => {
|
14
14
|
launchWorkspace('stock-item-rules-form-workspace', {
|
15
|
-
workspaceTitle: t('addStockRule', 'Add
|
15
|
+
workspaceTitle: t('addStockRule', 'Add stock rule'),
|
16
16
|
stockItemUuid,
|
17
17
|
});
|
18
18
|
}, [stockItemUuid, t]);
|