datastake-daf 0.6.810 → 0.6.812
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/components/index.js +1338 -1330
- package/dist/layouts/index.js +484 -460
- package/dist/pages/index.js +1562 -551
- package/dist/style/datastake/mapbox-gl.css +330 -0
- package/dist/utils/index.js +484 -460
- package/package.json +1 -1
- package/public/Vegetation/damage-from-insects-default.svg +2 -0
- package/public/Vegetation/dry-or-dead-default.svg +2 -0
- package/public/Vegetation/healthy-default.svg +2 -0
- package/public/Vegetation/yellowing.svg +2 -0
- package/src/@daf/core/components/Dashboard/Widget/FaunaWidget/index.jsx +1 -2
- package/src/@daf/core/components/Icon/configs/Droplets.js +9 -0
- package/src/@daf/core/components/Icon/configs/TrendUp.js +8 -0
- package/src/@daf/core/components/Icon/configs/index.js +4 -0
- package/src/@daf/pages/Summary/Activities/Monitoring/components/BiodiversityAndHabitat/index.jsx +2 -2
- package/src/@daf/pages/Summary/Activities/Monitoring/helper.js +24 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/BiodiversityHabitat/InvasiveSpecies.jsx +107 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/BiodiversityHabitat/ObservedFauna.jsx +80 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/BiodiversityHabitat/Stats.jsx +62 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/BiodiversityHabitat/index.jsx +109 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/KeyInformation/index.jsx +8 -4
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/PlantedSpecies.jsx +21 -9
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/SeedlingsHeight.jsx +36 -2
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/Stats.jsx +3 -3
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/VegetationHealth.jsx +19 -8
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/index.jsx +13 -9
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/SoilWaterProfile/SalinityLevels.jsx +100 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/SoilWaterProfile/SoilType.jsx +84 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/SoilWaterProfile/Stats.jsx +72 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/SoilWaterProfile/WaterQuality.jsx +84 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/SoilWaterProfile/index.jsx +101 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/chartHelpers.js +102 -0
- package/src/@daf/pages/Summary/Activities/MonitoringCampaign/index.jsx +8 -2
- package/src/@daf/utils/numbers.js +1 -1
package/package.json
CHANGED
|
@@ -6,3 +6,5 @@
|
|
|
6
6
|
<path d="M46.6985 104.257H45.1672V100.217L41.6946 94.3924H43.4036L45.9192 98.7469H45.967L48.4827 94.3924H50.178L46.6985 100.217V104.257ZM52.885 97.9471C51.8186 97.9471 51.0461 98.7264 50.9641 99.868H54.7307C54.6965 98.7127 53.9651 97.9471 52.885 97.9471ZM54.7239 102.083H56.1389C55.927 103.416 54.6213 104.346 52.9534 104.346C50.8 104.346 49.4602 102.896 49.4602 100.572C49.4602 98.2479 50.8137 96.7372 52.8918 96.7372C54.9289 96.7372 56.2141 98.1522 56.2141 100.401V100.921H50.9573V101.01C50.9573 102.295 51.7639 103.142 52.9807 103.142C53.842 103.142 54.5188 102.732 54.7239 102.083ZM57.4719 104.257V93.9481H58.9553V104.257H57.4719ZM60.6028 104.257V93.9481H62.0862V104.257H60.6028ZM66.8508 104.346C64.7043 104.346 63.3371 102.883 63.3371 100.545C63.3371 98.2137 64.7112 96.7372 66.8508 96.7372C68.9905 96.7372 70.3577 98.2069 70.3577 100.545C70.3577 102.883 68.9973 104.346 66.8508 104.346ZM66.8508 103.115C68.1086 103.115 68.8537 102.165 68.8537 100.545C68.8537 98.9247 68.1086 97.9676 66.8508 97.9676C65.593 97.9676 64.8411 98.9315 64.8411 100.545C64.8411 102.165 65.593 103.115 66.8508 103.115ZM81.2678 96.8329L79.2239 104.257H77.6926L76.1135 98.6649H76.0793L74.5139 104.257H72.9895L70.9387 96.8329H72.4153L73.7961 102.712H73.8235L75.3957 96.8329H76.8176L78.3967 102.712H78.4241L79.8049 96.8329H81.2678ZM82.2659 104.257V96.8329H83.7493V104.257H82.2659ZM83.011 95.7733C82.5325 95.7733 82.1428 95.3905 82.1428 94.9188C82.1428 94.4334 82.5325 94.0643 83.011 94.0643C83.4895 94.0643 83.8791 94.4334 83.8791 94.9188C83.8791 95.3905 83.4895 95.7733 83.011 95.7733ZM85.3284 104.257V96.8329H86.7434V98.0838H86.7707C87.2219 97.2088 87.967 96.7508 89.1155 96.7508C90.7561 96.7508 91.6926 97.7899 91.6926 99.4989V104.257H90.2092V99.7791C90.2092 98.6512 89.6897 98.0223 88.6028 98.0223C87.4817 98.0223 86.8118 98.8016 86.8118 99.9706V104.257H85.3284ZM96.3274 103.006C97.5305 103.006 98.3303 102.021 98.3303 100.524C98.3303 99.0204 97.5305 98.0155 96.3274 98.0155C95.1311 98.0155 94.3586 98.9998 94.3586 100.524C94.3586 102.042 95.1311 103.006 96.3274 103.006ZM96.3342 106.93C94.55 106.93 93.2785 106.102 93.135 104.831H94.6321C94.7961 105.405 95.4866 105.767 96.3957 105.767C97.5715 105.767 98.3303 105.152 98.3303 104.181V102.958H98.2961C97.8655 103.758 96.9905 104.236 95.9377 104.236C94.0852 104.236 92.841 102.78 92.841 100.517C92.841 98.2274 94.0715 96.7577 95.9719 96.7577C97.0246 96.7577 97.886 97.243 98.344 98.0633H98.3713V96.8329H99.8069V104.065C99.8069 105.836 98.4739 106.93 96.3342 106.93ZM51.9758 127.257V116.948H53.4592V127.257H51.9758ZM58.135 120.947C57.0686 120.947 56.2961 121.726 56.2141 122.868H59.9807C59.9465 121.713 59.2151 120.947 58.135 120.947ZM59.9739 125.083H61.3889C61.177 126.416 59.8713 127.346 58.2034 127.346C56.05 127.346 54.7102 125.896 54.7102 123.572C54.7102 121.248 56.0637 119.737 58.1418 119.737C60.1789 119.737 61.4641 121.152 61.4641 123.401V123.921H56.2073V124.01C56.2073 125.295 57.0139 126.142 58.2307 126.142C59.092 126.142 59.7688 125.732 59.9739 125.083ZM65.2375 126.149C66.3381 126.149 67.1721 125.445 67.1721 124.468V123.887L65.3674 124.01C64.3557 124.071 63.8293 124.447 63.8293 125.103C63.8293 125.739 64.383 126.149 65.2375 126.149ZM64.8411 127.332C63.3577 127.332 62.3323 126.457 62.3323 125.131C62.3323 123.832 63.3371 123.08 65.1692 122.964L67.1721 122.848V122.273C67.1721 121.426 66.6047 120.961 65.6135 120.961C64.8069 120.961 64.219 121.378 64.0891 122.02H62.7014C62.7424 120.708 63.9866 119.737 65.6545 119.737C67.4661 119.737 68.635 120.694 68.635 122.164V127.257H67.22V126.019H67.1858C66.7756 126.826 65.8528 127.332 64.8411 127.332ZM76.428 119.833L73.7551 127.257H72.176L69.4963 119.833H71.0618L72.9553 125.794H72.9895L74.8899 119.833H76.428ZM80.2014 120.947C79.135 120.947 78.3625 121.726 78.2805 122.868H82.0471C82.0129 121.713 81.2815 120.947 80.2014 120.947ZM82.0403 125.083H83.4553C83.2434 126.416 81.9377 127.346 80.2698 127.346C78.1164 127.346 76.7766 125.896 76.7766 123.572C76.7766 121.248 78.1301 119.737 80.2082 119.737C82.2453 119.737 83.5305 121.152 83.5305 123.401V123.921H78.2737V124.01C78.2737 125.295 79.0803 126.142 80.2971 126.142C81.1584 126.142 81.8352 125.732 82.0403 125.083ZM84.6037 121.945C84.6037 120.639 85.7727 119.744 87.4817 119.744C89.1086 119.744 90.2844 120.66 90.3186 121.952H88.9241C88.8625 121.296 88.2952 120.886 87.4475 120.886C86.6067 120.886 86.0461 121.275 86.0461 121.863C86.0461 122.314 86.4153 122.622 87.2014 122.813L88.4319 123.107C89.9289 123.47 90.4827 124.01 90.4827 125.103C90.4827 126.43 89.2248 127.346 87.427 127.346C85.6975 127.346 84.5149 126.45 84.4055 125.11H85.8684C85.9846 125.821 86.5588 126.211 87.5022 126.211C88.425 126.211 89.0061 125.828 89.0061 125.226C89.0061 124.755 88.7121 124.509 87.9328 124.31L86.6067 123.982C85.2668 123.654 84.6037 122.971 84.6037 121.945Z" fill="#6C737F"/>
|
|
7
7
|
</svg>
|
|
8
8
|
|
|
9
|
+
|
|
10
|
+
|
|
@@ -29,8 +29,7 @@ export default function FaunaWidget({
|
|
|
29
29
|
$itemHeight={itemHeight}
|
|
30
30
|
>
|
|
31
31
|
{faunaConfig.map((item) => {
|
|
32
|
-
|
|
33
|
-
// Otherwise use default SVG
|
|
32
|
+
|
|
34
33
|
const isPresent = Array.isArray(faunaPresent) && faunaPresent.includes(item.key);
|
|
35
34
|
const shouldUseColored = isPresent;
|
|
36
35
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
const config = {
|
|
3
|
+
viewBox: '0 0 17 18',
|
|
4
|
+
children: (
|
|
5
|
+
<path d="M8.71667 3.73333C9.2898 2.8176 9.69608 1.80754 9.91667 0.75C10.3333 2.83333 11.5833 4.83333 13.25 6.16667C14.9167 7.5 15.75 9.08333 15.75 10.75C15.7548 11.9019 15.4174 13.0293 14.7807 13.9892C14.1439 14.9492 13.2365 15.6985 12.1734 16.1421C11.1104 16.5857 9.93952 16.7037 8.80931 16.4811C7.67911 16.2585 6.64044 15.7053 5.825 14.8917M4.08333 11.8167C5.91667 11.8167 7.41667 10.2917 7.41667 8.44167C7.41667 7.475 6.94167 6.55833 5.99167 5.78333C5.04167 5.00833 4.325 3.85833 4.08333 2.65C3.84167 3.85833 3.13333 5.01667 2.175 5.78333C1.21667 6.55 0.75 7.48333 0.75 8.44167C0.75 10.2917 2.25 11.8167 4.08333 11.8167Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
6
|
+
),
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default config;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const config = {
|
|
2
|
+
viewBox: '0 0 19 10',
|
|
3
|
+
children: (
|
|
4
|
+
<path d="M17.4167 0.75L10.8595 7.30719C10.5295 7.63721 10.3645 7.80221 10.1742 7.86404C10.0068 7.91842 9.82652 7.91842 9.65915 7.86404C9.46888 7.80221 9.30387 7.6372 8.97386 7.30719L6.69281 5.02614C6.36279 4.69613 6.19779 4.53112 6.00751 4.4693C5.84014 4.41492 5.65986 4.41492 5.49249 4.4693C5.30221 4.53112 5.1372 4.69613 4.80719 5.02614L0.75 9.08333M17.4167 0.75H11.5833M17.4167 0.75V6.58333" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
|
|
5
|
+
),
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default config;
|
|
@@ -228,6 +228,8 @@ import SpacingHeight from "./SpacingHeight";
|
|
|
228
228
|
import SpacingWidth from "./SpacingWidth";
|
|
229
229
|
import Up from "./Up";
|
|
230
230
|
import Down from "./Down";
|
|
231
|
+
import TrendUp from "./TrendUp";
|
|
232
|
+
import Droplets from "./Droplets";
|
|
231
233
|
|
|
232
234
|
const config = {
|
|
233
235
|
AppAdmin,
|
|
@@ -460,6 +462,8 @@ const config = {
|
|
|
460
462
|
SpacingWidth,
|
|
461
463
|
Up,
|
|
462
464
|
Down,
|
|
465
|
+
TrendUp,
|
|
466
|
+
Droplets
|
|
463
467
|
};
|
|
464
468
|
|
|
465
469
|
export default config;
|
|
@@ -237,6 +237,30 @@ export const getMapDataFromActivity = (activityData, t) => {
|
|
|
237
237
|
});
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
// Entry 4: Generic locationCheck marker (independent - show if it exists)
|
|
241
|
+
const locationCheckLat = activityData?.locationCheck?.latitude;
|
|
242
|
+
const locationCheckLng = activityData?.locationCheck?.longitude;
|
|
243
|
+
if (isValidCoordinate(locationCheckLat) && isValidCoordinate(locationCheckLng)) {
|
|
244
|
+
mapData.push({
|
|
245
|
+
_id: {},
|
|
246
|
+
id: `${activityData?.id || activityData?.datastakeId || 'locationcheck'}-locationcheck`,
|
|
247
|
+
// Include area if it exists, so marker can show on top of polygon
|
|
248
|
+
area: area && area.length >= 3 ? area : null,
|
|
249
|
+
color: baseColor,
|
|
250
|
+
gps: {
|
|
251
|
+
latitude: typeof locationCheckLat === 'number' ? locationCheckLat : parseFloat(locationCheckLat),
|
|
252
|
+
longitude: typeof locationCheckLng === 'number' ? locationCheckLng : parseFloat(locationCheckLng),
|
|
253
|
+
},
|
|
254
|
+
name: t("Location Check"),
|
|
255
|
+
plotName: locationName,
|
|
256
|
+
territoryTitle: t("Associated Plot"),
|
|
257
|
+
datastakeId: `${datastakeId}-locationcheck`,
|
|
258
|
+
markerColor: "#016C6E",
|
|
259
|
+
sources: null,
|
|
260
|
+
link: null,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
240
264
|
// Return mapData even if empty - let the map component handle empty arrays
|
|
241
265
|
return mapData;
|
|
242
266
|
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Widget, RadarChart } from '../../../../../../../../src/index.js';
|
|
3
|
+
|
|
4
|
+
// Define the specific 5 categories to show in radar chart
|
|
5
|
+
const RADAR_CATEGORIES = ['spiders', 'scaleInsects', 'caterpillars', 'ants', 'unidentifiedPests'];
|
|
6
|
+
|
|
7
|
+
// Custom labels for the radar chart
|
|
8
|
+
const RADAR_LABELS = {
|
|
9
|
+
'spiders': 'Spiders',
|
|
10
|
+
'scaleInsects': 'Scale insects',
|
|
11
|
+
'caterpillars': 'Caterpillars',
|
|
12
|
+
'ants': 'Ants',
|
|
13
|
+
'unidentifiedPests': 'Unidentified pests'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const InvasiveSpecies = ({
|
|
17
|
+
invasiveSpeciesChart,
|
|
18
|
+
t = (s) => s,
|
|
19
|
+
options = {}
|
|
20
|
+
}) => {
|
|
21
|
+
|
|
22
|
+
const chartData = useMemo(() => {
|
|
23
|
+
const speciesOptions = options?.invasiveSpecies || [];
|
|
24
|
+
|
|
25
|
+
// Create a map of existing data
|
|
26
|
+
const dataMap = new Map();
|
|
27
|
+
if (invasiveSpeciesChart && Array.isArray(invasiveSpeciesChart)) {
|
|
28
|
+
invasiveSpeciesChart.forEach(item => {
|
|
29
|
+
if (item?.invasiveSpecies) {
|
|
30
|
+
dataMap.set(item.invasiveSpecies, Number(item?.count) || 0);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Create chart data for all 5 radar categories
|
|
36
|
+
const data = RADAR_CATEGORIES.map((categoryValue) => {
|
|
37
|
+
return {
|
|
38
|
+
item: RADAR_LABELS[categoryValue] || categoryValue,
|
|
39
|
+
score: dataMap.get(categoryValue) || 0,
|
|
40
|
+
invasiveSpecies: categoryValue
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return data;
|
|
45
|
+
}, [invasiveSpeciesChart, options]);
|
|
46
|
+
|
|
47
|
+
const maxScore = useMemo(() => {
|
|
48
|
+
if (!chartData || chartData.length === 0) return 100;
|
|
49
|
+
const max = Math.max(...chartData.map(item => item.score || 0));
|
|
50
|
+
return max > 0 ? Math.ceil(max * 1.2) : 100;
|
|
51
|
+
}, [chartData]);
|
|
52
|
+
|
|
53
|
+
const isEmpty = useMemo(() => {
|
|
54
|
+
// Never empty since we always show 5 categories
|
|
55
|
+
return false;
|
|
56
|
+
}, []);
|
|
57
|
+
|
|
58
|
+
console.log('InvasiveSpecies - chartData:', chartData);
|
|
59
|
+
return (
|
|
60
|
+
<Widget
|
|
61
|
+
title={t("Invasive Species")}
|
|
62
|
+
className="with-border-header h-w-btn-header"
|
|
63
|
+
>
|
|
64
|
+
|
|
65
|
+
{isEmpty ? (
|
|
66
|
+
<div style={{
|
|
67
|
+
display: 'flex',
|
|
68
|
+
alignItems: 'center',
|
|
69
|
+
justifyContent: 'center',
|
|
70
|
+
height: '100%',
|
|
71
|
+
color: '#999'
|
|
72
|
+
}}>
|
|
73
|
+
{t("No data available")}
|
|
74
|
+
</div>
|
|
75
|
+
) : (
|
|
76
|
+
<RadarChart
|
|
77
|
+
data={chartData}
|
|
78
|
+
xFieldKey="item"
|
|
79
|
+
yFieldKey="score"
|
|
80
|
+
animated={true}
|
|
81
|
+
height={400}
|
|
82
|
+
score={{
|
|
83
|
+
max: maxScore,
|
|
84
|
+
min: 0
|
|
85
|
+
}}
|
|
86
|
+
renderTooltipContent={(title, data) => {
|
|
87
|
+
if (!data || data.length === 0) return {};
|
|
88
|
+
const item = data[0]?.data || data[0];
|
|
89
|
+
return {
|
|
90
|
+
title: title,
|
|
91
|
+
items: [
|
|
92
|
+
{
|
|
93
|
+
label: t("Sightings"),
|
|
94
|
+
value: item?.score || 0,
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
)}
|
|
101
|
+
|
|
102
|
+
</Widget>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export default InvasiveSpecies;
|
|
107
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Widget, BarChart } from '../../../../../../../../src/index.js';
|
|
3
|
+
import { calculateNiceAxisConfig, mergeDefaultCategories } from '../chartHelpers.js';
|
|
4
|
+
|
|
5
|
+
const ObservedFauna = ({
|
|
6
|
+
observedFaunaChart,
|
|
7
|
+
t = (s) => s,
|
|
8
|
+
options = {}
|
|
9
|
+
}) => {
|
|
10
|
+
const chartData = useMemo(() => {
|
|
11
|
+
const allFaunaTypes = options?.faunaObserved || [];
|
|
12
|
+
|
|
13
|
+
if (allFaunaTypes.length === 0) {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const mergedData = mergeDefaultCategories(
|
|
18
|
+
observedFaunaChart,
|
|
19
|
+
allFaunaTypes,
|
|
20
|
+
'fauna',
|
|
21
|
+
'count',
|
|
22
|
+
'label',
|
|
23
|
+
'value'
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// Rename 'label' to 'type' for BarChart compatibility
|
|
27
|
+
return mergedData.map(item => ({
|
|
28
|
+
type: item.label,
|
|
29
|
+
value: item.value,
|
|
30
|
+
fauna: item.fauna
|
|
31
|
+
}));
|
|
32
|
+
}, [observedFaunaChart, options]);
|
|
33
|
+
|
|
34
|
+
const xAxisConfig = useMemo(() => {
|
|
35
|
+
return calculateNiceAxisConfig(
|
|
36
|
+
chartData,
|
|
37
|
+
'value',
|
|
38
|
+
1.2, // multiplier: 20% padding
|
|
39
|
+
{
|
|
40
|
+
min: 0,
|
|
41
|
+
max: 10,
|
|
42
|
+
tickMethod: () => [0, 2, 4, 6, 8, 10]
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
}, [chartData]);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Widget
|
|
49
|
+
title={t("Observed Fauna")}
|
|
50
|
+
className="with-border-header h-w-btn-header"
|
|
51
|
+
>
|
|
52
|
+
<BarChart
|
|
53
|
+
data={chartData}
|
|
54
|
+
yFieldKey="type"
|
|
55
|
+
xFieldKey="value"
|
|
56
|
+
animated={true}
|
|
57
|
+
color="#00AEB1"
|
|
58
|
+
xAxisConfig={xAxisConfig}
|
|
59
|
+
renderTooltipContent={(title, data) => {
|
|
60
|
+
if (!data || data.length === 0) return {};
|
|
61
|
+
const item = data[0]?.data || data[0];
|
|
62
|
+
return {
|
|
63
|
+
title: title,
|
|
64
|
+
subTitle: t("Sightings"),
|
|
65
|
+
items: [
|
|
66
|
+
{
|
|
67
|
+
label: t("Count"),
|
|
68
|
+
value: item?.value || 0,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
}}
|
|
73
|
+
/>
|
|
74
|
+
|
|
75
|
+
</Widget>
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default ObservedFauna;
|
|
80
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { StatCard } from '../../../../../../../../src/index.js';
|
|
3
|
+
import { calculateStatChange } from '../../../../../../utils/numbers.js';
|
|
4
|
+
|
|
5
|
+
const Stats = ({
|
|
6
|
+
faunaSightings,
|
|
7
|
+
invasiveSpeciesSightings,
|
|
8
|
+
t = (s) => s
|
|
9
|
+
}) => {
|
|
10
|
+
const faunaSightingsChange = useMemo(() => {
|
|
11
|
+
if (!faunaSightings) return null;
|
|
12
|
+
return calculateStatChange(
|
|
13
|
+
{
|
|
14
|
+
current: Number(faunaSightings.current) || 0,
|
|
15
|
+
previous: Number(faunaSightings.previous) || 0,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
tooltipText: t("In comparison to last period"),
|
|
19
|
+
format: 'absolute',
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
}, [faunaSightings, t]);
|
|
23
|
+
|
|
24
|
+
const invasiveSpeciesSightingsChange = useMemo(() => {
|
|
25
|
+
if (!invasiveSpeciesSightings) return null;
|
|
26
|
+
return calculateStatChange(
|
|
27
|
+
{
|
|
28
|
+
current: Number(invasiveSpeciesSightings.current) || 0,
|
|
29
|
+
previous: Number(invasiveSpeciesSightings.previous) || 0,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
tooltipText: t("In comparison to last period"),
|
|
33
|
+
format: 'absolute',
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
}, [invasiveSpeciesSightings, t]);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div style={{ display: "flex", gap: "24px", marginBottom: "24px" }}>
|
|
40
|
+
<section style={{ flex: 1 }}>
|
|
41
|
+
<StatCard
|
|
42
|
+
title={t("Fauna Sightings")}
|
|
43
|
+
value={faunaSightings ? Number(faunaSightings.current).toLocaleString() : "0"}
|
|
44
|
+
icon="Fish"
|
|
45
|
+
change={faunaSightingsChange}
|
|
46
|
+
/>
|
|
47
|
+
</section>
|
|
48
|
+
|
|
49
|
+
<section style={{ flex: 1 }}>
|
|
50
|
+
<StatCard
|
|
51
|
+
title={t("Invasive Species Sightings")}
|
|
52
|
+
value={invasiveSpeciesSightings ? Number(invasiveSpeciesSightings.current).toLocaleString() : "0"}
|
|
53
|
+
icon="Ant"
|
|
54
|
+
change={invasiveSpeciesSightingsChange}
|
|
55
|
+
/>
|
|
56
|
+
</section>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default Stats;
|
|
62
|
+
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Widget } from '../../../../../../../../src/index.js';
|
|
3
|
+
import { useWidgetFetch } from '../../../../../../hooks/useWidgetFetch.js';
|
|
4
|
+
import Stats from './Stats.jsx';
|
|
5
|
+
import ObservedFauna from './ObservedFauna.jsx';
|
|
6
|
+
import InvasiveSpecies from './InvasiveSpecies.jsx';
|
|
7
|
+
|
|
8
|
+
const BiodiversityHabitat = ({
|
|
9
|
+
id,
|
|
10
|
+
getSummaryDetail,
|
|
11
|
+
loading = false,
|
|
12
|
+
t = (s) => s,
|
|
13
|
+
options = {}
|
|
14
|
+
}) => {
|
|
15
|
+
const defaultConfig = useMemo(
|
|
16
|
+
() => ({
|
|
17
|
+
basepath: "events/monitoring-campaign-summary",
|
|
18
|
+
url: `/summary/${id}/biodiversity-habitat`,
|
|
19
|
+
stop: !id,
|
|
20
|
+
}),
|
|
21
|
+
[id],
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const customGetData = useMemo(() => {
|
|
25
|
+
if (getSummaryDetail && id) {
|
|
26
|
+
return ({ url, params = {} }) => {
|
|
27
|
+
const match = url.match(/\/summary\/[^/]+\/(.+)/);
|
|
28
|
+
if (match) {
|
|
29
|
+
const [, type] = match;
|
|
30
|
+
return getSummaryDetail(id, type, params);
|
|
31
|
+
}
|
|
32
|
+
throw new Error(`Invalid URL format: ${url}`);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}, [getSummaryDetail, id]);
|
|
37
|
+
|
|
38
|
+
const { loading: outcomesLoading, data: outcomesData } = useWidgetFetch({
|
|
39
|
+
config: defaultConfig,
|
|
40
|
+
getData: customGetData
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const {
|
|
44
|
+
faunaSightings,
|
|
45
|
+
invasiveSpecies,
|
|
46
|
+
previousCycleFaunaSightings,
|
|
47
|
+
previousCycleInvasiveSpecies,
|
|
48
|
+
observedFauna
|
|
49
|
+
} = outcomesData || {};
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
const transformedFaunaSightings = useMemo(() => {
|
|
53
|
+
const current = Array.isArray(faunaSightings) && faunaSightings.length > 0
|
|
54
|
+
? faunaSightings.reduce((sum, item) => sum + (Number(item?.count) || 0), 0)
|
|
55
|
+
: 0;
|
|
56
|
+
const previous = Array.isArray(previousCycleFaunaSightings) && previousCycleFaunaSightings.length > 0
|
|
57
|
+
? previousCycleFaunaSightings.reduce((sum, item) => sum + (Number(item?.count) || 0), 0)
|
|
58
|
+
: 0;
|
|
59
|
+
return { current, previous };
|
|
60
|
+
}, [faunaSightings, previousCycleFaunaSightings]);
|
|
61
|
+
|
|
62
|
+
const transformedInvasiveSpecies = useMemo(() => {
|
|
63
|
+
const current = Array.isArray(invasiveSpecies) && invasiveSpecies.length > 0
|
|
64
|
+
? invasiveSpecies.reduce((sum, item) => sum + (Number(item?.count) || 0), 0)
|
|
65
|
+
: 0;
|
|
66
|
+
const previous = Array.isArray(previousCycleInvasiveSpecies) && previousCycleInvasiveSpecies.length > 0
|
|
67
|
+
? previousCycleInvasiveSpecies.reduce((sum, item) => sum + (Number(item?.count) || 0), 0)
|
|
68
|
+
: 0;
|
|
69
|
+
return { current, previous };
|
|
70
|
+
}, [invasiveSpecies, previousCycleInvasiveSpecies]);
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<section>
|
|
75
|
+
<Widget
|
|
76
|
+
title={t("Biodiversity & Habitat")}
|
|
77
|
+
loading={loading || outcomesLoading}
|
|
78
|
+
className="with-border-header h-w-btn-header"
|
|
79
|
+
>
|
|
80
|
+
<Stats
|
|
81
|
+
faunaSightings={transformedFaunaSightings}
|
|
82
|
+
invasiveSpeciesSightings={transformedInvasiveSpecies}
|
|
83
|
+
t={t}
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
<div style={{ display: "flex", gap: "24px" }}>
|
|
87
|
+
<section style={{ flex: 1 }}>
|
|
88
|
+
<ObservedFauna
|
|
89
|
+
observedFaunaChart={observedFauna}
|
|
90
|
+
t={t}
|
|
91
|
+
options={options}
|
|
92
|
+
/>
|
|
93
|
+
</section>
|
|
94
|
+
|
|
95
|
+
<InvasiveSpecies
|
|
96
|
+
invasiveSpeciesChart={invasiveSpecies}
|
|
97
|
+
t={t}
|
|
98
|
+
options={options}
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
</div>
|
|
102
|
+
</Widget>
|
|
103
|
+
|
|
104
|
+
</section>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export default BiodiversityHabitat;
|
|
109
|
+
|
package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/KeyInformation/index.jsx
CHANGED
|
@@ -7,8 +7,8 @@ const KeyInformation = ({ id, t = () => { }, getSummaryDetail, loading = false }
|
|
|
7
7
|
|
|
8
8
|
const defaultConfig = useMemo(
|
|
9
9
|
() => ({
|
|
10
|
-
basepath: "events/monitoring-campaign",
|
|
11
|
-
url:
|
|
10
|
+
basepath: "events/monitoring-campaign-summary",
|
|
11
|
+
url: `/${id}/key-information`,
|
|
12
12
|
stop: !id,
|
|
13
13
|
}),
|
|
14
14
|
[id],
|
|
@@ -16,10 +16,14 @@ const KeyInformation = ({ id, t = () => { }, getSummaryDetail, loading = false }
|
|
|
16
16
|
|
|
17
17
|
const customGetData = useMemo(() => {
|
|
18
18
|
if (getSummaryDetail && id) {
|
|
19
|
-
return (
|
|
20
|
-
const
|
|
19
|
+
return (rest) => {
|
|
20
|
+
const { url, filters: restFilters } = rest;
|
|
21
|
+
const match = url.match(/\/[^/]+\/(.+)/);
|
|
21
22
|
if (match) {
|
|
22
23
|
const [, type] = match;
|
|
24
|
+
const params = {
|
|
25
|
+
...(restFilters || {}),
|
|
26
|
+
};
|
|
23
27
|
return getSummaryDetail(id, type, params);
|
|
24
28
|
}
|
|
25
29
|
throw new Error(`Invalid URL format: ${url}`);
|
|
@@ -2,28 +2,40 @@ import React, { useMemo, useCallback } from 'react';
|
|
|
2
2
|
import { Widget, PieChart } from '../../../../../../../../src/index.js';
|
|
3
3
|
import { renderTooltipJsx } from '../../../../../../utils/tooltip.js';
|
|
4
4
|
|
|
5
|
-
const COLORS = ['#
|
|
5
|
+
const COLORS = ['#6AD99E', '#F5C2AC', '#F0A888', '#DF571E', '#C04B19', '#9B3D14', '#7A2F0F'];
|
|
6
6
|
|
|
7
7
|
const PlantedSpecies = ({
|
|
8
8
|
plantedSpeciesChart,
|
|
9
|
-
t = (s) => s
|
|
9
|
+
t = (s) => s,
|
|
10
|
+
options = {}
|
|
10
11
|
}) => {
|
|
12
|
+
|
|
13
|
+
const optionsMap = useMemo(() => {
|
|
14
|
+
if (!options || !Array.isArray(options)) return {};
|
|
15
|
+
return options.reduce((acc, option) => {
|
|
16
|
+
if (option?.value) {
|
|
17
|
+
acc[option.value] = option.label;
|
|
18
|
+
}
|
|
19
|
+
return acc;
|
|
20
|
+
}, {});
|
|
21
|
+
}, [options]);
|
|
22
|
+
|
|
11
23
|
const pieData = useMemo(() => {
|
|
12
24
|
const data = plantedSpeciesChart || [];
|
|
13
|
-
const total = data.reduce((sum, item) => sum + (Number(item?.
|
|
25
|
+
const total = data.reduce((sum, item) => sum + (Number(item?.count) || 0), 0);
|
|
14
26
|
|
|
15
27
|
return data.map((item, index) => ({
|
|
16
|
-
value: Number(item?.
|
|
17
|
-
percent: total > 0 ? (Number(item?.
|
|
28
|
+
value: Number(item?.count) || 0,
|
|
29
|
+
percent: total > 0 ? (Number(item?.count) || 0) / total : 0,
|
|
18
30
|
color: COLORS[index % COLORS.length],
|
|
19
|
-
label: item?.
|
|
20
|
-
key: item?.
|
|
31
|
+
label: optionsMap[item?.name] || item?.name || '',
|
|
32
|
+
key: item?.name || `item-${index}`,
|
|
21
33
|
}));
|
|
22
|
-
}, [plantedSpeciesChart]);
|
|
34
|
+
}, [plantedSpeciesChart, optionsMap]);
|
|
23
35
|
|
|
24
36
|
const isEmpty = useMemo(() => {
|
|
25
37
|
return !plantedSpeciesChart || plantedSpeciesChart.length === 0 ||
|
|
26
|
-
plantedSpeciesChart.every(item => !item?.
|
|
38
|
+
plantedSpeciesChart.every(item => !item?.count || Number(item.count) === 0);
|
|
27
39
|
}, [plantedSpeciesChart]);
|
|
28
40
|
|
|
29
41
|
const getTooltipChildren = useCallback(
|
|
@@ -1,10 +1,43 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
import { Widget, ColumnChart } from '../../../../../../../../src/index.js';
|
|
3
|
+
import { calculateNiceAxisConfig, mergeDefaultCategories } from '../chartHelpers.js';
|
|
4
|
+
|
|
5
|
+
// Default height ranges to always display
|
|
6
|
+
const DEFAULT_HEIGHT_RANGES = [
|
|
7
|
+
{ value: '0-10', label: '0-10 cm' },
|
|
8
|
+
{ value: '11-20', label: '11-20 cm' },
|
|
9
|
+
{ value: '21-30', label: '21-30 cm' },
|
|
10
|
+
{ value: '30+', label: '30+ cm' }
|
|
11
|
+
];
|
|
3
12
|
|
|
4
13
|
const SeedlingsHeight = ({
|
|
5
14
|
seedlingsHeightChart,
|
|
6
15
|
t = (s) => s
|
|
7
16
|
}) => {
|
|
17
|
+
const chartData = useMemo(() => {
|
|
18
|
+
return mergeDefaultCategories(
|
|
19
|
+
seedlingsHeightChart,
|
|
20
|
+
DEFAULT_HEIGHT_RANGES,
|
|
21
|
+
'range',
|
|
22
|
+
'count',
|
|
23
|
+
'label',
|
|
24
|
+
'value'
|
|
25
|
+
);
|
|
26
|
+
}, [seedlingsHeightChart]);
|
|
27
|
+
|
|
28
|
+
const yAxisConfig = useMemo(() => {
|
|
29
|
+
return calculateNiceAxisConfig(
|
|
30
|
+
chartData,
|
|
31
|
+
'value',
|
|
32
|
+
2, // multiplier: double the max value
|
|
33
|
+
{
|
|
34
|
+
min: 0,
|
|
35
|
+
max: 20,
|
|
36
|
+
tickMethod: () => [0, 5, 10, 15, 20]
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}, [chartData]);
|
|
40
|
+
|
|
8
41
|
return (
|
|
9
42
|
<Widget
|
|
10
43
|
title={t("Seedlings Height")}
|
|
@@ -13,12 +46,13 @@ const SeedlingsHeight = ({
|
|
|
13
46
|
<div className="flex flex-1 flex-column justify-content-center">
|
|
14
47
|
<div className="flex justify-content-center w-full">
|
|
15
48
|
<ColumnChart
|
|
16
|
-
data={
|
|
49
|
+
data={chartData}
|
|
17
50
|
xFieldKey="label"
|
|
18
51
|
yFieldKey="value"
|
|
19
52
|
animated={true}
|
|
20
53
|
height={200}
|
|
21
54
|
color="#016C6E"
|
|
55
|
+
yAxis={yAxisConfig}
|
|
22
56
|
renderTooltipContent={(title, data) => {
|
|
23
57
|
if (!data || data.length === 0) return {};
|
|
24
58
|
const item = data[0]?.data || data[0];
|
package/src/@daf/pages/Summary/Activities/MonitoringCampaign/components/MangroveGrowth/Stats.jsx
CHANGED
|
@@ -56,7 +56,7 @@ const Stats = ({
|
|
|
56
56
|
<StatCard
|
|
57
57
|
title={t("Survival Rate")}
|
|
58
58
|
value={survivalRate ? Number(survivalRate.current).toLocaleString() : "0"}
|
|
59
|
-
icon="
|
|
59
|
+
icon="TrendUp"
|
|
60
60
|
change={survivalRateChange}
|
|
61
61
|
/>
|
|
62
62
|
</section>
|
|
@@ -65,7 +65,7 @@ const Stats = ({
|
|
|
65
65
|
<StatCard
|
|
66
66
|
title={t("Average Height")}
|
|
67
67
|
value={averageHeight ? Number(averageHeight.current).toLocaleString() + " cm" : "0 cm"}
|
|
68
|
-
icon="
|
|
68
|
+
icon="SpacingHeight"
|
|
69
69
|
change={averageHeightChange}
|
|
70
70
|
/>
|
|
71
71
|
</section>
|
|
@@ -74,7 +74,7 @@ const Stats = ({
|
|
|
74
74
|
<StatCard
|
|
75
75
|
title={t("Average Diameter")}
|
|
76
76
|
value={averageDiameter ? Number(averageDiameter.current).toLocaleString() + " mm" : "0 mm"}
|
|
77
|
-
icon="
|
|
77
|
+
icon="Tree"
|
|
78
78
|
change={averageDiameterChange}
|
|
79
79
|
/>
|
|
80
80
|
</section>
|