datastake-daf 0.6.787 → 0.6.789
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/build/favicon.ico +0 -0
- package/build/logo192.png +0 -0
- package/build/logo512.png +0 -0
- package/build/manifest.json +25 -0
- package/build/robots.txt +3 -0
- package/dist/components/index.js +588 -729
- package/dist/pages/index.js +775 -34
- package/dist/services/index.js +1 -10
- package/dist/utils/index.js +12 -28
- package/package.json +1 -1
- package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/ActivityIndicators.stories.js +24 -0
- package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/index.jsx +1 -0
- package/src/@daf/core/components/Dashboard/Widget/ActivityIndicators/style.js +34 -0
- package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/KeyIndicators.stories.js +39 -0
- package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/LabelWithIcon.jsx +38 -0
- package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/index.jsx +16 -3
- package/src/@daf/core/components/Dashboard/Widget/KeyIndicators/style.js +33 -0
- package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/TopContributors/hook.js +1 -0
- package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/TopContributors/index.jsx +1 -1
- package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/UserGrowth/hook.js +1 -1
- package/src/@daf/core/components/Screens/Admin/AdminDashboard/components/UserStatistics/UserGrowth/index.jsx +1 -1
- package/src/@daf/core/components/Screens/Admin/AdminModals/AddUser/index.jsx +1 -0
- package/src/@daf/core/components/Screens/Admin/AdminModals/CombineLocation/index.jsx +1 -1
- package/src/@daf/core/components/Screens/Admin/AdminModals/NewAccount/index.jsx +1 -1
- package/src/@daf/core/components/Screens/Admin/AdminScreens/Dashboard.jsx +2 -2
- package/src/@daf/core/components/Screens/Admin/AdminScreens/Location.jsx +5 -5
- package/src/@daf/core/components/Screens/Admin/AdminScreens/Subjects.jsx +2 -2
- package/src/@daf/core/components/Screens/Admin/AdminTables/LocationTable/index.jsx +5 -23
- package/src/@daf/core/components/Screens/Admin/AdminTables/SubjectsTable/columns.js +36 -36
- package/src/@daf/core/components/Screens/Admin/AdminTables/SubjectsTable/index.jsx +21 -12
- package/src/@daf/core/components/Screens/Admin/AdminViews/components/Users/helper.js +8 -13
- package/src/@daf/core/components/Screens/Admin/AdminViews/components/Users/index.jsx +2 -2
- package/src/@daf/core/components/Screens/Admin/adminRoutes.js +2 -2
- package/src/@daf/pages/Summary/Activities/Monitoring/components/ActivityImagery/index.jsx +29 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/components/ActivityLocation/index.jsx +94 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/PlantedSpecies/index.jsx +56 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/SeedlingsHeight/index.jsx +121 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/components/SurvivalRate/index.jsx +94 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/index.jsx +54 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/components/WorkersDistribution/index.jsx +49 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/config.js +51 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/helper.js +236 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/index.jsx +66 -0
- package/src/@daf/pages/Summary/Minesite/components/StakeholderMapping/index.js +1 -1
- package/src/@daf/services/AdminService.js +3 -12
- package/src/@daf/services/DashboardService.js +1 -2
- package/src/@daf/utils/filters.js +89 -89
- package/src/constants/locales/en/translation.js +0 -3
- package/src/constants/locales/fr/translation.js +1 -1
- package/src/constants/locales/sp/translation.js +1 -1
- package/src/pages.js +1 -0
- package/src/@daf/core/components/Screens/Admin/AdminTables/LocationTable/column.js +0 -224
- package/src/@daf/core/components/Screens/Admin/AdminTables/LocationTable/helper.js +0 -65
- package/src/@daf/pages/SelfAssesment/components/AssociatedInformationTable/columns.js +0 -180
- package/src/@daf/pages/SelfAssesment/components/AssociatedInformationTable/config.js +0 -0
- package/src/@daf/pages/SelfAssesment/components/AssociatedInformationTable/index.jsx +0 -27
- package/src/@daf/pages/SelfAssesment/components/OrgInformationTable/columns.js +0 -157
- package/src/@daf/pages/SelfAssesment/components/OrgInformationTable/config.js +0 -31
- package/src/@daf/pages/SelfAssesment/components/OrgInformationTable/index.js +0 -77
- package/src/@daf/pages/SelfAssesment/components/ProductionSiteTable/columns.js +0 -117
- package/src/@daf/pages/SelfAssesment/components/ProductionSiteTable/index.jsx +0 -54
- package/src/@daf/pages/SelfAssesment/index.jsx +0 -0
|
@@ -2,7 +2,7 @@ import { useState, useMemo } from "react";
|
|
|
2
2
|
import { useAdminTable } from "../hook";
|
|
3
3
|
import AdminTable from "../components/index.jsx";
|
|
4
4
|
import DAFTable from "../../../../Table/index.jsx";
|
|
5
|
-
import { theme, Tag
|
|
5
|
+
import { theme, Tag } from "antd";
|
|
6
6
|
import CustomIcon from "../../../../Icon/CustomIcon.jsx";
|
|
7
7
|
import {
|
|
8
8
|
getTabs,
|
|
@@ -67,7 +67,7 @@ export default function SubjectsTable({
|
|
|
67
67
|
return {
|
|
68
68
|
category: config.options?.category,
|
|
69
69
|
country: config.options?.countries,
|
|
70
|
-
sources: [],
|
|
70
|
+
sources: [], //TODO: add sources logic and make sure you only show unique sources only once
|
|
71
71
|
};
|
|
72
72
|
}, [config.options]);
|
|
73
73
|
|
|
@@ -113,15 +113,25 @@ export default function SubjectsTable({
|
|
|
113
113
|
breadcrumbs={breadcrumbs}
|
|
114
114
|
>
|
|
115
115
|
{selectedSubjects.length > 0 && (
|
|
116
|
-
<div
|
|
116
|
+
<div
|
|
117
|
+
className="flex flex-row ml-6 mt-5"
|
|
118
|
+
style={{
|
|
119
|
+
flexWrap: "wrap",
|
|
120
|
+
gap: "8px",
|
|
121
|
+
}}
|
|
122
|
+
>
|
|
117
123
|
{selectedSubjects.map((account) => (
|
|
118
124
|
<Tag
|
|
119
125
|
key={account.userId}
|
|
120
126
|
className="flex flex-row gap-2 items-center"
|
|
121
127
|
onClick={() =>
|
|
122
|
-
setSelectedSubjects((prev) =>
|
|
128
|
+
setSelectedSubjects((prev) =>
|
|
129
|
+
prev.filter((a) => a.datastakeId !== account.datastakeId),
|
|
130
|
+
)
|
|
123
131
|
}
|
|
124
|
-
style={{
|
|
132
|
+
style={{
|
|
133
|
+
cursor: "pointer",
|
|
134
|
+
}}
|
|
125
135
|
>
|
|
126
136
|
<span>{account.datastakeId}</span>
|
|
127
137
|
<CustomIcon name="Close" size={10} />
|
|
@@ -150,20 +160,19 @@ export default function SubjectsTable({
|
|
|
150
160
|
<CombineSubjectsModal
|
|
151
161
|
isOpen={isCombineModalOpen}
|
|
152
162
|
t={t}
|
|
153
|
-
onClose={() =>
|
|
163
|
+
onClose={() => {
|
|
164
|
+
setIsModalOpen(false);
|
|
165
|
+
}}
|
|
154
166
|
onSuccess={(data) => {
|
|
155
167
|
setIsModalOpen(false);
|
|
156
168
|
setLoading(true);
|
|
157
|
-
message.success(t("Subjects successfully merged."))
|
|
158
169
|
if (typeof mergeSubjectsFunction === 'function') {
|
|
159
|
-
mergeSubjectsFunction(data)
|
|
160
|
-
|
|
161
|
-
fetchData();
|
|
162
|
-
});
|
|
170
|
+
mergeSubjectsFunction(data);
|
|
171
|
+
setSelectedSubjects([])
|
|
163
172
|
}
|
|
164
173
|
}}
|
|
165
174
|
selectedSubjects={selectedSubjects}
|
|
166
|
-
selectOptions={selectOptions}
|
|
175
|
+
selectOptions={selectOptions || {}}
|
|
167
176
|
module={module}
|
|
168
177
|
entity={headerTitle}
|
|
169
178
|
/>
|
|
@@ -167,7 +167,10 @@ export const getColumns = ({
|
|
|
167
167
|
return cols.filter((v) => v.show);
|
|
168
168
|
};
|
|
169
169
|
|
|
170
|
-
export const checkboxConfig = {
|
|
170
|
+
export const checkboxConfig = {
|
|
171
|
+
name: "Name",
|
|
172
|
+
datastakeId: "ID",
|
|
173
|
+
};
|
|
171
174
|
|
|
172
175
|
export const selectFiltersConfig = {
|
|
173
176
|
userRole: {
|
|
@@ -191,17 +194,9 @@ export const selectFiltersConfig = {
|
|
|
191
194
|
};
|
|
192
195
|
|
|
193
196
|
export const filtersConfig = {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
export const defaultUrlParams = {
|
|
198
|
-
search: "",
|
|
199
|
-
userRole: null,
|
|
200
|
-
status: null,
|
|
197
|
+
name: "",
|
|
198
|
+
datastakeId: "",
|
|
201
199
|
};
|
|
202
200
|
|
|
203
|
-
export const
|
|
204
|
-
|
|
205
|
-
userRole: null,
|
|
206
|
-
status: null,
|
|
207
|
-
};
|
|
201
|
+
export const defaultUrlParams = {};
|
|
202
|
+
export const defaultTableFilters = {};
|
|
@@ -60,10 +60,10 @@ export default function Users({
|
|
|
60
60
|
userRole: userRoles.filter((u) => !u.isForAppAdmin),
|
|
61
61
|
status: accountStatuses,
|
|
62
62
|
};
|
|
63
|
-
}, [userRoles
|
|
63
|
+
}, [userRoles]);
|
|
64
64
|
|
|
65
65
|
const canClearSearch = useMemo(() => {
|
|
66
|
-
return !!activeFilters.search
|
|
66
|
+
return !!activeFilters.search;
|
|
67
67
|
}, [activeFilters]);
|
|
68
68
|
|
|
69
69
|
const onDeleteUserClick = useCallback(
|
|
@@ -104,7 +104,7 @@ export function getAdminRoutes(config) {
|
|
|
104
104
|
...(typeof useAdminLocationConfig === "function"
|
|
105
105
|
? [
|
|
106
106
|
{
|
|
107
|
-
path: "
|
|
107
|
+
path: "subjects/location",
|
|
108
108
|
key: `${APP_PREFIX}_ADMIN_SUBJECTS_LOCATIONS`,
|
|
109
109
|
exact: true,
|
|
110
110
|
visible: (user) => userIsAdmin(user),
|
|
@@ -115,7 +115,7 @@ export function getAdminRoutes(config) {
|
|
|
115
115
|
...(typeof useAdminSubjectsConfig === "function"
|
|
116
116
|
? [
|
|
117
117
|
{
|
|
118
|
-
path: "
|
|
118
|
+
path: "subjects/stakeholder",
|
|
119
119
|
key: `${APP_PREFIX}_ADMIN_SUBJECTS_STAKEHOLDERS`,
|
|
120
120
|
exact: true,
|
|
121
121
|
visible: (user) => userIsAdmin(user),
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { ImageCarousel } from '../../../../../../../../src/index.js';
|
|
3
|
+
import { getActivityImages } from '../../helper';
|
|
4
|
+
import { useResizeContext } from '../../../../../../../../src/context';
|
|
5
|
+
|
|
6
|
+
const ActivityImagery = ({
|
|
7
|
+
activityData,
|
|
8
|
+
loading = false,
|
|
9
|
+
t = (s) => s
|
|
10
|
+
}) => {
|
|
11
|
+
const { isCollapsed, isNestedSidebarCollapsed } = useResizeContext();
|
|
12
|
+
const images = useMemo(() => getActivityImages(activityData), [activityData]);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div style={{ maxWidth: "70%", width: "calc(100% - 405px)" }}>
|
|
16
|
+
<ImageCarousel
|
|
17
|
+
loading={loading}
|
|
18
|
+
images={images}
|
|
19
|
+
title={t("straatos::activity-imagery")}
|
|
20
|
+
key={`${isCollapsed}-${isNestedSidebarCollapsed}`}
|
|
21
|
+
customArrows={true}
|
|
22
|
+
activeDotColor="#003435"
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default ActivityImagery;
|
|
29
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Widget, MineSiteMap } from '../../../../../../../../src/index.js';
|
|
3
|
+
import { getMapDataFromActivity } from '../../helper';
|
|
4
|
+
import { convertDMS } from '../../../../../../../../src/helpers/Map';
|
|
5
|
+
import CustomIcon from '../../../../../../../../src/@daf/core/components/Icon/CustomIcon.jsx';
|
|
6
|
+
|
|
7
|
+
const ActivityLocation = ({
|
|
8
|
+
activityData,
|
|
9
|
+
loading = false,
|
|
10
|
+
t = (s) => s
|
|
11
|
+
}) => {
|
|
12
|
+
const mapData = useMemo(() => getMapDataFromActivity(activityData, t), [activityData, t]);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<section>
|
|
16
|
+
<Widget
|
|
17
|
+
title={t("Activity Location")}
|
|
18
|
+
className="no-px h-w-btn-header no-pt-body no-p-body no-pb-body"
|
|
19
|
+
style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
|
|
20
|
+
>
|
|
21
|
+
<div style={{ flex: 1, minHeight: 0 }}>
|
|
22
|
+
<MineSiteMap
|
|
23
|
+
loading={loading}
|
|
24
|
+
t={t}
|
|
25
|
+
isSatellite={true}
|
|
26
|
+
app={"straatos"}
|
|
27
|
+
type={'location-territory'}
|
|
28
|
+
showSider={false}
|
|
29
|
+
user={null}
|
|
30
|
+
data={mapData}
|
|
31
|
+
maxZoom={18}
|
|
32
|
+
primaryLink={true}
|
|
33
|
+
style={{ height: '100%', width: '100%' }}
|
|
34
|
+
renderTooltipForLocation={(data) => {
|
|
35
|
+
const coordinates = data.gps?.latitude && data.gps?.longitude
|
|
36
|
+
? convertDMS(data.gps.latitude, data.gps.longitude)
|
|
37
|
+
: null;
|
|
38
|
+
|
|
39
|
+
if (!coordinates) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const isActivityEnd = data.name === t("Activity End") || data.id?.includes('-departure');
|
|
44
|
+
const iconColor = isActivityEnd ? "#FF7A45" : "#016C6E";
|
|
45
|
+
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
label: t("Coordinates"),
|
|
49
|
+
|
|
50
|
+
value: (
|
|
51
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '6px', flexWrap: 'nowrap' }}>
|
|
52
|
+
{/* Latitude icon (vertical) */}
|
|
53
|
+
<div style={{ display: 'flex', alignItems: 'center' }}>
|
|
54
|
+
<CustomIcon
|
|
55
|
+
name="SpacingHeight"
|
|
56
|
+
width={14}
|
|
57
|
+
height={14}
|
|
58
|
+
color={iconColor}
|
|
59
|
+
/>
|
|
60
|
+
<span style={{ fontWeight: 600, marginLeft: '4px' }}>{coordinates[0]}</span>
|
|
61
|
+
</div>
|
|
62
|
+
{/* Longitude icon (horizontal) */}
|
|
63
|
+
<div style={{ display: 'flex', alignItems: 'center' }}>
|
|
64
|
+
<CustomIcon
|
|
65
|
+
name="SpacingWidth"
|
|
66
|
+
width={14}
|
|
67
|
+
height={14}
|
|
68
|
+
color={iconColor}
|
|
69
|
+
/>
|
|
70
|
+
<span style={{ fontWeight: 600, marginLeft: '4px' }}>{coordinates[1]}</span>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
),
|
|
74
|
+
},
|
|
75
|
+
];
|
|
76
|
+
}}
|
|
77
|
+
renderTooltipForTerritory={(data) => {
|
|
78
|
+
return [
|
|
79
|
+
{
|
|
80
|
+
label: t("Plot Name"),
|
|
81
|
+
value: data.plotName || data.name || "--",
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
}}
|
|
85
|
+
link={true}
|
|
86
|
+
/>
|
|
87
|
+
</div>
|
|
88
|
+
</Widget>
|
|
89
|
+
</section>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default ActivityLocation;
|
|
94
|
+
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { ActivityIndicators } from '../../../../../../../../../../src/index.js';
|
|
3
|
+
|
|
4
|
+
const PlantedSpecies = ({
|
|
5
|
+
activityData,
|
|
6
|
+
loading = false,
|
|
7
|
+
t = (s) => s
|
|
8
|
+
}) => {
|
|
9
|
+
const speciesConfig = useMemo(() => {
|
|
10
|
+
// Extract planted species from activityData
|
|
11
|
+
// Assuming the data structure might have plantedSpecies array or similar
|
|
12
|
+
const species = activityData?.plantedSpecies || activityData?.mangroveSpecies || [];
|
|
13
|
+
|
|
14
|
+
// If species is an array, map it to config format
|
|
15
|
+
if (Array.isArray(species)) {
|
|
16
|
+
return species.map((speciesItem, index) => {
|
|
17
|
+
const speciesName = typeof speciesItem === 'string'
|
|
18
|
+
? speciesItem
|
|
19
|
+
: speciesItem?.name || speciesItem?.species || `Species ${index + 1}`;
|
|
20
|
+
|
|
21
|
+
// Determine if species is selected/planted (you may need to adjust this logic)
|
|
22
|
+
const isSelected = typeof speciesItem === 'object'
|
|
23
|
+
? speciesItem?.selected !== false
|
|
24
|
+
: true;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
icon: 'Tree',
|
|
28
|
+
label: speciesName,
|
|
29
|
+
type: isSelected ? 'compliant' : 'notCompliant',
|
|
30
|
+
statusIcon: isSelected ? 'Check' : 'Close'
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Fallback: if no species data, show default species from image
|
|
36
|
+
return [
|
|
37
|
+
{ icon: 'Tree', label: 'Rhyzophora sp', type: 'compliant', statusIcon: 'Check' },
|
|
38
|
+
{ icon: 'Tree', label: 'Rhyzophora', type: 'notCompliant', statusIcon: 'Close' },
|
|
39
|
+
{ icon: 'Tree', label: 'Rhyzophora mangle', type: 'notCompliant', statusIcon: 'Close' }
|
|
40
|
+
];
|
|
41
|
+
}, [activityData]);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<ActivityIndicators
|
|
45
|
+
title={t("Planted Species")}
|
|
46
|
+
config={speciesConfig}
|
|
47
|
+
loading={loading}
|
|
48
|
+
widgetClassName="h-w-btn-header"
|
|
49
|
+
t={t}
|
|
50
|
+
className="single-column"
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default PlantedSpecies;
|
|
56
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Widget, ColumnChart } from '../../../../../../../../../../src/index.js';
|
|
3
|
+
|
|
4
|
+
const SeedlingsHeight = ({
|
|
5
|
+
activityData,
|
|
6
|
+
loading = false,
|
|
7
|
+
t = (s) => s
|
|
8
|
+
}) => {
|
|
9
|
+
const heightData = useMemo(() => {
|
|
10
|
+
// Extract seedlings height from activityData
|
|
11
|
+
// Assuming the data might have averageHeight, seedlingsHeight, or similar
|
|
12
|
+
const averageHeight = activityData?.averageHeight ||
|
|
13
|
+
activityData?.seedlingsHeight ||
|
|
14
|
+
activityData?.mangroveAverageHeight ||
|
|
15
|
+
28; // Default from image
|
|
16
|
+
|
|
17
|
+
const heightValue = typeof averageHeight === 'number'
|
|
18
|
+
? averageHeight
|
|
19
|
+
: parseFloat(averageHeight) || 28;
|
|
20
|
+
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
23
|
+
label: t("Average Height"),
|
|
24
|
+
value: heightValue
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
}, [activityData, t]);
|
|
28
|
+
|
|
29
|
+
const renderTooltipContent = useMemo(() => {
|
|
30
|
+
return (title, data) => {
|
|
31
|
+
if (!data || data.length === 0) {
|
|
32
|
+
return {
|
|
33
|
+
title: t("Average Height"),
|
|
34
|
+
items: [
|
|
35
|
+
{
|
|
36
|
+
label: t("No Data"),
|
|
37
|
+
value: '-'
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const item = data[0];
|
|
44
|
+
const value = item?.value || item?.data?.value || 0;
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
title: t("Average Height"),
|
|
48
|
+
items: [
|
|
49
|
+
{
|
|
50
|
+
label: t("Average Height"),
|
|
51
|
+
value: `${value.toFixed(1)}cm`,
|
|
52
|
+
color: '#00AEB1'
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
}, [t]);
|
|
58
|
+
|
|
59
|
+
const isEmpty = useMemo(() => {
|
|
60
|
+
return !activityData?.averageHeight &&
|
|
61
|
+
!activityData?.seedlingsHeight &&
|
|
62
|
+
!activityData?.mangroveAverageHeight;
|
|
63
|
+
}, [activityData]);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<Widget
|
|
67
|
+
loading={loading}
|
|
68
|
+
title={t("Seedlings Height")}
|
|
69
|
+
className="with-border-header h-w-btn-header"
|
|
70
|
+
>
|
|
71
|
+
<div
|
|
72
|
+
style={{
|
|
73
|
+
display: 'flex',
|
|
74
|
+
flexDirection: 'column',
|
|
75
|
+
minHeight: '250px',
|
|
76
|
+
padding: '20px 0'
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
<ColumnChart
|
|
80
|
+
data={isEmpty ? [] : heightData}
|
|
81
|
+
xFieldKey="label"
|
|
82
|
+
yFieldKey="value"
|
|
83
|
+
color="#00AEB1"
|
|
84
|
+
height={250}
|
|
85
|
+
animated={true}
|
|
86
|
+
renderTooltipContent={renderTooltipContent}
|
|
87
|
+
yAxis={{
|
|
88
|
+
min: 0,
|
|
89
|
+
max: 35,
|
|
90
|
+
tickMethod: () => [0, 5, 10, 15, 20, 25, 30, 35],
|
|
91
|
+
label: {
|
|
92
|
+
formatter: (v) => `${v}cm`
|
|
93
|
+
}
|
|
94
|
+
}}
|
|
95
|
+
xAxis={{
|
|
96
|
+
label: {
|
|
97
|
+
formatter: () => ''
|
|
98
|
+
}
|
|
99
|
+
}}
|
|
100
|
+
tooltipConfig={{
|
|
101
|
+
showTitle: true
|
|
102
|
+
}}
|
|
103
|
+
/>
|
|
104
|
+
{!isEmpty && (
|
|
105
|
+
<div style={{
|
|
106
|
+
marginTop: '16px',
|
|
107
|
+
textAlign: 'center',
|
|
108
|
+
fontSize: '14px',
|
|
109
|
+
color: '#475467',
|
|
110
|
+
fontWeight: 500
|
|
111
|
+
}}>
|
|
112
|
+
{t("Average Height")}: {heightData[0]?.value.toFixed(0)}cm
|
|
113
|
+
</div>
|
|
114
|
+
)}
|
|
115
|
+
</div>
|
|
116
|
+
</Widget>
|
|
117
|
+
);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export default SeedlingsHeight;
|
|
121
|
+
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Widget, DonutPie } from '../../../../../../../../../../src/index.js';
|
|
3
|
+
|
|
4
|
+
const SurvivalRate = ({
|
|
5
|
+
activityData,
|
|
6
|
+
loading = false,
|
|
7
|
+
t = (s) => s
|
|
8
|
+
}) => {
|
|
9
|
+
const survivalData = useMemo(() => {
|
|
10
|
+
// Extract survival rate from activityData
|
|
11
|
+
// Assuming the data might have survivalRate as a percentage (0-100)
|
|
12
|
+
const survivalRate = activityData?.survivalRate || activityData?.mangroveSurvivalRate || 78;
|
|
13
|
+
const survivalPercent = typeof survivalRate === 'number' ? survivalRate : parseFloat(survivalRate) || 78;
|
|
14
|
+
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
type: t("Survival Rate"),
|
|
18
|
+
value: survivalPercent
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: t("Non-survival"),
|
|
22
|
+
value: 100 - survivalPercent
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
}, [activityData, t]);
|
|
26
|
+
|
|
27
|
+
const renderTooltipContent = useMemo(() => {
|
|
28
|
+
return (title, data) => {
|
|
29
|
+
if (!data || data.length === 0) {
|
|
30
|
+
return {
|
|
31
|
+
title: t("Survival Rate"),
|
|
32
|
+
items: [
|
|
33
|
+
{
|
|
34
|
+
label: t("No Data"),
|
|
35
|
+
value: '-'
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const item = data[0];
|
|
42
|
+
const value = item?.value || item?.data?.value || 0;
|
|
43
|
+
const itemType = item?.type || item?.data?.type || t("Survival Rate");
|
|
44
|
+
|
|
45
|
+
// Determine color based on item type
|
|
46
|
+
const itemColor = itemType === t("Survival Rate") ? '#00AEB1' : '#E8EDF3';
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
title: t("Survival Rate"),
|
|
50
|
+
items: [
|
|
51
|
+
{
|
|
52
|
+
label: itemType,
|
|
53
|
+
value: `${value.toFixed(1)}%`,
|
|
54
|
+
color: itemColor
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
}, [t]);
|
|
60
|
+
|
|
61
|
+
const isEmpty = useMemo(() => {
|
|
62
|
+
return !activityData?.survivalRate && !activityData?.mangroveSurvivalRate;
|
|
63
|
+
}, [activityData]);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<Widget
|
|
67
|
+
loading={loading}
|
|
68
|
+
title={t("Survival Rate")}
|
|
69
|
+
className="with-border-header h-w-btn-header"
|
|
70
|
+
>
|
|
71
|
+
|
|
72
|
+
{/* <DonutPie
|
|
73
|
+
angleField="value"
|
|
74
|
+
color={[
|
|
75
|
+
'#E8EDF3'
|
|
76
|
+
]}
|
|
77
|
+
colorField="type"
|
|
78
|
+
data={[]}
|
|
79
|
+
height={200}
|
|
80
|
+
innerRadius={0.78}
|
|
81
|
+
radius={1}
|
|
82
|
+
renderTooltipContent={() => { }}
|
|
83
|
+
tooltip
|
|
84
|
+
tooltipConfig={{
|
|
85
|
+
showTitle: false
|
|
86
|
+
}}
|
|
87
|
+
/> */}
|
|
88
|
+
|
|
89
|
+
</Widget>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default SurvivalRate;
|
|
94
|
+
|
package/src/@daf/pages/Summary/Activities/Monitoring/components/MangroveGrowthAndSurvival/index.jsx
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PlantedSpecies from './components/PlantedSpecies/index.jsx';
|
|
3
|
+
import SurvivalRate from './components/SurvivalRate/index.jsx';
|
|
4
|
+
import SeedlingsHeight from './components/SeedlingsHeight/index.jsx';
|
|
5
|
+
import styled from 'styled-components';
|
|
6
|
+
import { Widget } from '../../../../../../../../src/index.js';
|
|
7
|
+
|
|
8
|
+
const Container = styled.div`
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
11
|
+
gap: 24px;
|
|
12
|
+
width: 100%;
|
|
13
|
+
|
|
14
|
+
@media (max-width: 768px) {
|
|
15
|
+
grid-template-columns: 1fr;
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
const MangroveGrowthAndSurvival = ({
|
|
20
|
+
activityData,
|
|
21
|
+
loading = false,
|
|
22
|
+
t = (s) => s
|
|
23
|
+
}) => {
|
|
24
|
+
return (
|
|
25
|
+
|
|
26
|
+
<Widget
|
|
27
|
+
title={t("Mangrove Growth & Survival")}
|
|
28
|
+
className="with-border-header h-w-btn-header"
|
|
29
|
+
>
|
|
30
|
+
<section>
|
|
31
|
+
<Container>
|
|
32
|
+
<PlantedSpecies
|
|
33
|
+
activityData={activityData}
|
|
34
|
+
loading={loading}
|
|
35
|
+
t={t}
|
|
36
|
+
/>
|
|
37
|
+
<SurvivalRate
|
|
38
|
+
activityData={activityData}
|
|
39
|
+
loading={loading}
|
|
40
|
+
t={t}
|
|
41
|
+
/>
|
|
42
|
+
<SeedlingsHeight
|
|
43
|
+
activityData={activityData}
|
|
44
|
+
loading={loading}
|
|
45
|
+
t={t}
|
|
46
|
+
/>
|
|
47
|
+
</Container>
|
|
48
|
+
</section>
|
|
49
|
+
</Widget>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default MangroveGrowthAndSurvival;
|
|
54
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React, { useMemo, useCallback } from 'react';
|
|
2
|
+
import { Widget, PieChart } from '../../../../../../../../src/index.js';
|
|
3
|
+
import { getGenderDistributionData, isGenderDistributionEmpty, calculateGenderPieData, getGenderTooltipChildren } from '../../helper';
|
|
4
|
+
import { renderTooltipJsx } from '../../../../../../../../src/utils';
|
|
5
|
+
|
|
6
|
+
const WorkersDistribution = ({
|
|
7
|
+
activityData,
|
|
8
|
+
loading = false,
|
|
9
|
+
t = (s) => s
|
|
10
|
+
}) => {
|
|
11
|
+
const genderDistributionData = useMemo(() => getGenderDistributionData(activityData), [activityData]);
|
|
12
|
+
const isEmpty = useMemo(() => isGenderDistributionEmpty(genderDistributionData), [genderDistributionData]);
|
|
13
|
+
const pieData = useMemo(() => calculateGenderPieData(genderDistributionData), [genderDistributionData]);
|
|
14
|
+
|
|
15
|
+
const getTooltipChildren = useCallback(
|
|
16
|
+
(item) => getGenderTooltipChildren(item, isEmpty, genderDistributionData, t, renderTooltipJsx),
|
|
17
|
+
[t, isEmpty, genderDistributionData],
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Widget
|
|
22
|
+
loading={loading}
|
|
23
|
+
title={<div>{t("Workers Distribution")}</div>}
|
|
24
|
+
className="with-border-header h-w-btn-header "
|
|
25
|
+
>
|
|
26
|
+
<div
|
|
27
|
+
style={{
|
|
28
|
+
marginTop: "auto",
|
|
29
|
+
marginBottom: "auto",
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
<PieChart
|
|
33
|
+
mouseXOffset={10}
|
|
34
|
+
mouseYOffset={10}
|
|
35
|
+
changeOpacityOnHover={false}
|
|
36
|
+
data={pieData}
|
|
37
|
+
doConstraints={false}
|
|
38
|
+
isPie
|
|
39
|
+
t={t}
|
|
40
|
+
isEmpty={isEmpty}
|
|
41
|
+
getTooltipChildren={getTooltipChildren}
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
</Widget>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default WorkersDistribution;
|
|
49
|
+
|