datastake-daf 0.6.826 → 0.6.827
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 +1228 -1195
- package/dist/pages/index.js +77 -58
- package/dist/style/datastake/mapbox-gl.css +330 -0
- package/package.json +1 -1
- package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CommunityParticipation/JobsTimeline/index.jsx +32 -9
- package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/HealthAndSafety/helper.js +48 -43
- package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleIndicators/HealthAndSafety/index.jsx +17 -5
- package/src/@daf/pages/Summary/Activities/PlantingCycle/components/CycleOutcomes/PlantingActivitiesTimeline.jsx +12 -5
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
// Custom tooltip labels per field/value
|
|
3
|
+
const FIELD_TOOLTIP_LABELS = {
|
|
4
|
+
aidKitAccessible: {
|
|
5
|
+
compliant: "Available",
|
|
6
|
+
notCompliant: "Not available",
|
|
7
|
+
empty: "No data",
|
|
8
|
+
},
|
|
9
|
+
hsTrainingConfirmation: {
|
|
10
|
+
compliant: "Training delivered",
|
|
11
|
+
notCompliant: "No training",
|
|
12
|
+
empty: "No data",
|
|
13
|
+
},
|
|
14
|
+
duosFormed: {
|
|
15
|
+
compliant: "Duos formed",
|
|
16
|
+
notCompliant: "Not implemented",
|
|
17
|
+
empty: "No data",
|
|
18
|
+
},
|
|
19
|
+
presenceOfChildren: {
|
|
20
|
+
compliant: "None reported",
|
|
21
|
+
notCompliant: "Children present",
|
|
22
|
+
empty: "No data",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
1
26
|
const HEALTH_SAFETY_COLORS = {
|
|
2
27
|
compliant: '#016C6E',
|
|
3
28
|
notCompliant: '#F97066',
|
|
@@ -11,11 +36,6 @@ const getIndicatorType = (value) => {
|
|
|
11
36
|
return "empty";
|
|
12
37
|
};
|
|
13
38
|
|
|
14
|
-
/**
|
|
15
|
-
* Gets health and safety distribution data from activity data
|
|
16
|
-
* @param {Object} activityData - Activity data object
|
|
17
|
-
* @returns {Object} Distribution object with compliant, notCompliant, and empty counts
|
|
18
|
-
*/
|
|
19
39
|
export const getHealthAndSafetyDistributionData = (activityData) => {
|
|
20
40
|
// Define health and safety indicator fields
|
|
21
41
|
const indicators = [
|
|
@@ -42,23 +62,12 @@ export const getHealthAndSafetyDistributionData = (activityData) => {
|
|
|
42
62
|
return distribution;
|
|
43
63
|
};
|
|
44
64
|
|
|
45
|
-
/**
|
|
46
|
-
* Checks if the health and safety distribution data is empty
|
|
47
|
-
* @param {Object} healthAndSafetyDistributionData - Distribution object
|
|
48
|
-
* @returns {boolean} True if all values are 0 or empty
|
|
49
|
-
*/
|
|
50
65
|
export const isHealthAndSafetyDistributionEmpty = (healthAndSafetyDistributionData) => {
|
|
51
66
|
return Object.values(healthAndSafetyDistributionData).every(val => !val || val === 0);
|
|
52
67
|
};
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* @param {Object} healthAndSafetyDistributionData - Distribution object
|
|
57
|
-
* @param {Function} t - Translation function
|
|
58
|
-
* @returns {Array} Array of pie chart data points with value, percent, color, label, and key
|
|
59
|
-
*/
|
|
60
|
-
export const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData, t) => {
|
|
61
|
-
const total = Object.values(healthAndSafetyDistributionData).reduce((all, val) => all + (val || 0), 0);
|
|
69
|
+
export const calculateHealthAndSafetyPieData = (data, t, selectedField) => {
|
|
70
|
+
const total = Object.values(data).reduce((a, v) => a + (v || 0), 0);
|
|
62
71
|
|
|
63
72
|
const labels = {
|
|
64
73
|
compliant: t("Available"),
|
|
@@ -66,31 +75,27 @@ export const calculateHealthAndSafetyPieData = (healthAndSafetyDistributionData,
|
|
|
66
75
|
empty: t("Not answered"),
|
|
67
76
|
};
|
|
68
77
|
|
|
69
|
-
return Object.keys(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
key: key,
|
|
78
|
-
};
|
|
79
|
-
});
|
|
78
|
+
return Object.keys(data).map((key) => ({
|
|
79
|
+
value: data[key] || 0,
|
|
80
|
+
percent: total > 0 ? (data[key] || 0) / total : 0,
|
|
81
|
+
color: HEALTH_SAFETY_COLORS[key] || '#D9D9D9',
|
|
82
|
+
label: labels[key] || key,
|
|
83
|
+
key,
|
|
84
|
+
keyOfField: selectedField, // <-- ADD THIS
|
|
85
|
+
}));
|
|
80
86
|
};
|
|
81
87
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
export const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafetyDistributionData, t, renderTooltipJsx, tooltipTitle = "Health and Safety") => {
|
|
88
|
+
|
|
89
|
+
export const getHealthAndSafetyTooltipChildren = (
|
|
90
|
+
item,
|
|
91
|
+
isEmpty,
|
|
92
|
+
healthAndSafetyDistributionData,
|
|
93
|
+
t,
|
|
94
|
+
renderTooltipJsx,
|
|
95
|
+
tooltipTitle = "Health and Safety",
|
|
96
|
+
selectedField
|
|
97
|
+
) => {
|
|
98
|
+
|
|
94
99
|
// If empty or no data, return null to display nothing
|
|
95
100
|
if (isEmpty || !Object.keys(healthAndSafetyDistributionData).length) {
|
|
96
101
|
return null;
|
|
@@ -104,10 +109,10 @@ export const getHealthAndSafetyTooltipChildren = (item, isEmpty, healthAndSafety
|
|
|
104
109
|
return null;
|
|
105
110
|
}
|
|
106
111
|
|
|
107
|
-
const labels = {
|
|
112
|
+
const labels = FIELD_TOOLTIP_LABELS[item?.keyOfField] || {
|
|
108
113
|
compliant: t("Available"),
|
|
109
114
|
notCompliant: t("Not available"),
|
|
110
|
-
empty: t("
|
|
115
|
+
empty: t("No data"),
|
|
111
116
|
};
|
|
112
117
|
|
|
113
118
|
// Filter items with values > 0
|
|
@@ -54,7 +54,6 @@ const HealthAndSafety = ({
|
|
|
54
54
|
getData: customGetData
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
// Process the fetched pie chart data
|
|
58
57
|
// The API returns data in format: [{count: 1, [field]: "null"}, {count: 1, [field]: "no"}, {count: 1, [field]: "yes"}]
|
|
59
58
|
const healthAndSafetyDistributionData = useMemo(() => {
|
|
60
59
|
if (!pieChartData) return { compliant: 0, notCompliant: 0, empty: 0 };
|
|
@@ -90,7 +89,10 @@ const HealthAndSafety = ({
|
|
|
90
89
|
}, [pieChartData, selectedField]);
|
|
91
90
|
|
|
92
91
|
const isEmpty = useMemo(() => isHealthAndSafetyDistributionEmpty(healthAndSafetyDistributionData), [healthAndSafetyDistributionData]);
|
|
93
|
-
const pieData = useMemo(() =>
|
|
92
|
+
const pieData = useMemo(() =>
|
|
93
|
+
calculateHealthAndSafetyPieData(healthAndSafetyDistributionData, t, selectedField),
|
|
94
|
+
[healthAndSafetyDistributionData, t, selectedField]);
|
|
95
|
+
|
|
94
96
|
|
|
95
97
|
// Get the label for the selected field to use as tooltip title
|
|
96
98
|
const selectedFieldLabel = useMemo(() => {
|
|
@@ -99,7 +101,16 @@ const HealthAndSafety = ({
|
|
|
99
101
|
}, [selectedField]);
|
|
100
102
|
|
|
101
103
|
const getTooltipChildren = useCallback(
|
|
102
|
-
(item) =>
|
|
104
|
+
(item) =>
|
|
105
|
+
getHealthAndSafetyTooltipChildren(
|
|
106
|
+
item,
|
|
107
|
+
isEmpty,
|
|
108
|
+
healthAndSafetyDistributionData,
|
|
109
|
+
t,
|
|
110
|
+
renderTooltipJsx,
|
|
111
|
+
selectedFieldLabel,
|
|
112
|
+
selectedField
|
|
113
|
+
),
|
|
103
114
|
[t, isEmpty, healthAndSafetyDistributionData, selectedFieldLabel],
|
|
104
115
|
);
|
|
105
116
|
|
|
@@ -110,8 +121,9 @@ const HealthAndSafety = ({
|
|
|
110
121
|
return (
|
|
111
122
|
<Widget
|
|
112
123
|
loading={loading || pieChartLoading}
|
|
113
|
-
title={<div>{t("Health
|
|
114
|
-
className="with-border-header h-w-btn-header
|
|
124
|
+
title={<div>{t("Operational Health & Safety")}</div>}
|
|
125
|
+
className="with-border-header h-w-btn-header"
|
|
126
|
+
description={t("Across all activities in this cycle.")}
|
|
115
127
|
addedHeader={
|
|
116
128
|
<>
|
|
117
129
|
<div className="flex-1" />
|
|
@@ -15,21 +15,28 @@ const PlantingActivitiesTimeline = ({
|
|
|
15
15
|
}) => {
|
|
16
16
|
const { timeFilter, setTimeFilter, formatDateAxis, processChartDateData } = useTimeFilter({ defaultFilter: 'monthly' });
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
const activitiesTimelineData = useMemo(() => {
|
|
20
20
|
const dataToProcess = (!activitiesTimelineChart || !Array.isArray(activitiesTimelineChart) || activitiesTimelineChart.length === 0)
|
|
21
21
|
? []
|
|
22
22
|
: activitiesTimelineChart;
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
// Process data without cumulative calculation (for activities timeline)
|
|
25
|
-
|
|
25
|
+
const processedData = processChartDateData({
|
|
26
26
|
mainData: dataToProcess,
|
|
27
27
|
isCumulative: false,
|
|
28
28
|
valueField: 'count',
|
|
29
29
|
});
|
|
30
|
+
|
|
31
|
+
// Remove trailing periods with 0 jobs (optional: remove all zero if you prefer)
|
|
32
|
+
let lastNonZeroIndex = processedData.length - 1;
|
|
33
|
+
while (lastNonZeroIndex >= 0 && (processedData[lastNonZeroIndex].jobs || 0) === 0) {
|
|
34
|
+
lastNonZeroIndex--;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return processedData.slice(0, lastNonZeroIndex + 1);
|
|
30
38
|
}, [activitiesTimelineChart, processChartDateData]);
|
|
31
|
-
|
|
32
|
-
// Calculate max value for Y-axis (default to 100 if all values are 0 or very small)
|
|
39
|
+
|
|
33
40
|
const maxActivitiesYValue = useMemo(() => {
|
|
34
41
|
if (!activitiesTimelineData || activitiesTimelineData.length === 0) {
|
|
35
42
|
return 100;
|